Linux命令(如find)在Python中获取的输出编码规范是什么?
在Unix系统中,GNU标准命令(如find)通过subprocess输出的编码规范是什么?
问题描述
使用Python的subprocess模块调用Unix系统的GNU标准命令(比如find)时,命令输出的解码编码应该如何选择?以下是示例代码:
import subprocess import shlex myProcess = subprocess.Popen(shlex.split('find ./dir -mindepth 1 -maxdepth 1 -type f -mtime +14'), stdout=subprocess.PIPE, stderr=subprocess.PIPE) outputs = myProcess.communicate() myStdout = outputs[0].read() myStderr = outputs[1].read() print(myStdout.decode('utf-8/ascii')) # ???
猜测用UTF-8或ASCII解码都能工作,但从官方标准角度,应该如何统一处理Unix标准命令的控制台输出?
回答
Unix系统中,GNU标准命令的输出编码由当前进程的locale设置决定,核心是LC_CTYPE环境变量对应的字符编码,具体规则和处理方式如下:
1. 默认编码继承逻辑
命令会继承调用它的Python进程的locale编码。你可以通过locale.getpreferredencoding(False)获取该编码,这也是Python 3.6+中subprocess启用text=True(或旧版的universal_newlines=True)参数时,默认使用的解码编码。
2. ASCII与UTF-8的适用场景
- 当系统locale为
C或POSIX时,默认编码是ASCII,但现代绝大多数Unix-like系统已经默认采用UTF-8作为locale编码(比如en_US.UTF-8)。 - 如果输出内容仅包含ASCII字符,两种解码方式都能正常工作;但如果涉及非ASCII字符(比如带特殊符号的文件名),用ASCII解码会直接抛出
UnicodeDecodeError。
3. 推荐的处理方式
方式一:自动匹配系统locale编码
直接使用系统当前的locale编码解码,避免硬编码:
import subprocess import shlex import locale encoding = locale.getpreferredencoding(False) cmd = shlex.split('find ./dir -mindepth 1 -maxdepth 1 -type f -mtime +14') process = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE) stdout_bytes, stderr_bytes = process.communicate() myStdout = stdout_bytes.decode(encoding) myStderr = stderr_bytes.decode(encoding) print(myStdout)
方式二:启用text参数自动处理
使用text=True参数让subprocess自动完成编码解码,无需手动处理字节流:
import subprocess import shlex cmd = shlex.split('find ./dir -mindepth 1 -maxdepth 1 -type f -mtime +14') # text=True 会自动用系统locale编码解码输出 process = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True) myStdout, myStderr = process.communicate() print(myStdout)
4. 强制指定UTF-8编码
如果需要确保命令输出以UTF-8编码返回,可以显式设置命令的LC_CTYPE环境变量:
import subprocess import shlex import os cmd = shlex.split('find ./dir -mindepth 1 -maxdepth 1 -type f -mtime +14') # 强制设置命令的locale为UTF-8 env = dict(os.environ, LC_CTYPE='en_US.UTF-8') process = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, env=env) stdout_bytes, stderr_bytes = process.communicate() myStdout = stdout_bytes.decode('utf-8') myStderr = stderr_bytes.decode('utf-8')
内容的提问来源于stack exchange,提问作者Jez
相关产品推荐
相关产品推荐

