遇到一个编码问题,问题简化如下:
在当前 desktop 目录下,有如下内容:
desktop $ ls
client.py server.py 中文测试
arcpy.txt codetest.py test.py
如上所示有一个中文命名的文件 ----> 中文测试
# -*- coding:utf-8 -*-
# python3.5.1
import os,sys
print (sys.getdefaultencoding()) #系统默认编码
dir_list = os.listdir()
for li in dir_list:
print (li)
输出如下:
utf-8
arcpy.txt
client.py
codetest.py
server.py
test.py
中文测试
可以看出默认编码为 utf-8,os.listdir()命令可以正常输出中文字符。
在使用 os.popen()时:
# -*- coding:utf-8 -*-
# python3.5.1
import os,sys
print (sys.getdefaultencoding()) #系统默认编码
dir_list = os.popen('ls','r').read()
for li in dir_list:
print (li)
报错如下:
utf-8
Traceback (most recent call last):
File "Desktop/codetest.py", line 8, in <module>
dir_list = os.popen('ls','r').read()
File "/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/encodings/ascii.py", line 26, in decode
return codecs.ascii_decode(input, self.errors)[0]
UnicodeDecodeError: 'ascii' codec can't decode byte 0xe4 in position 76: ordinal not in range(128)
既虽然默认编码为‘ utf-8',但 popen()读取目录时,依旧采用 ascii 编码,无法输出中文。 请问该如何解决?
1
zhjits 2018-05-29 09:30:32 +08:00
os.popen('ls', 'rb).read()
出来一个 bytes 对象,然后 decode 一下 |
2
wulala1234 OP @zhjits 查看 help(os.popen) 信息如下:
``` Help on function popen in module os: popen(cmd, mode='r', buffering=-1) # Supply os.popen() ``` 查询到的信息:参数 mode 只支持‘ r'(默认),'w',两种模式。。。 代入‘ rb ’,报错如下: ``` raise ValueError("invalid mode %r" % mode) ValueError: invalid mode 'rb' ``` |
3
hicdn 2018-05-29 10:19:12 +08:00
3.6.5 在 MAC OSX 下没有问题
|
4
est 2018-05-29 10:27:23 +08:00
io 模块里有个可以 wrap 一下的。
|
5
Sylv 2018-05-29 10:49:21 +08:00
os.popen 相当于 subprocess.Popen + io.TextIOWrapper,io.TextIOWrapper 默认使用的编码是 locale.getpreferredencoding(False)。
class io.TextIOWrapper(buffer, encoding=None, errors=None, newline=None, line_buffering=False, write_through=False) A buffered text stream over a BufferedIOBase binary stream. It inherits TextIOBase. encoding gives the name of the encoding that the stream will be decoded or encoded with. It defaults to locale.getpreferredencoding(False). locale.getpreferredencoding(do_setlocale=True) Return the encoding used for text data, according to user preferences. User preferences are expressed differently on different systems, and might not be available programmatically on some systems, so this function only returns a guess. 这个编码应该是由语言环境变量判断来的,在我这终端下( Mac OS )这个编码是 'UTF-8',所以你的代码在我这可以正常运行。在你的运行环境中这个编码是 'ascii',于是就出错了。 解决办法 1:改用 subprocess.Popen(cmd, shell=True, stdin=subprocess.PIPE),然后手动 decode('utf-8')。 解决办法 2:尝试修改你的语言环境变量,使得 locale.getpreferredencoding 返回 'UTF-8' 编码。 |
6
alvin666 2018-05-29 10:52:25 +08:00 via Android
五楼正解,popen 出来的通道是和你的 shell 的编码一致的,要么 bytes 然后 decode.encode,要么就改 shell 的编码
|
7
wulala1234 OP @hicdn 终端下( Mac OS X ) python3.5.1 和 python3.6.4 同运行正常。但在 sublime Text 3 中结果就是解码错误。
|
8
Sylv 2018-05-29 11:21:11 +08:00 1
@wulala1234
Sublime Text 的 Build System 也是用 subprocess.Popen 来运行用户脚本的,在这种情况下因为不存在 LANG 环境变量,所以 locale.getpreferredencoding 返回的是 'US-ASCII' 编码。 可以在 Build System 的配置文件 Python.sublime-build 中添加 LANG 变量来使其变为 'UTF-8': "env": {"PYTHONIOENCODING": "utf-8", "LANG": "en_US.UTF-8"} 参考: https://stackoverflow.com/questions/42101759/how-to-change-the-preferred-encoding-in-sublime-text-3-for-macos |
9
wulala1234 OP @Sylv 非常感谢您的回复。
在终端里 $locale LANG="zh_CN.UTF-8" LC_COLLATE="zh_CN.UTF-8" LC_CTYPE="zh_CN.UTF-8" LC_MESSAGES="zh_CN.UTF-8" LC_MONETARY="zh_CN.UTF-8" LC_NUMERIC="zh_CN.UTF-8" LC_TIME="zh_CN.UTF-8" LC_ALL= LC_ALL 无默认值 $ python 3.5 >>> import locale >>> locale.getpreferredencoding() 'UTF-8' 而在 sublime Text3 中 # python3.5 >>>import locale >>>print (locale.getpreferredencoding()) US-ASCII >>>print (locale.getdefaultlocale()) (None, None) 因为编码不同产生了错误。 您上面的回复是一种解决方式 还可以在代码中临时设置语言环境 >>>locale.setlocale(locale.LC_ALL,'zh_CN.UTF-8') 解决问题。 不过您的解决方式是一劳永逸的。 参考: https://docs.python.org/2/library/locale.html#locale.getdefaultlocale 接下来去查查 sys.getdefaultencoding()与 locale.getdefaultlocale()的区别了~~~ |
10
LEORChn 2019-11-29 02:37:50 +08:00
os.popen(cmd).buffer.read().decode(encoding='utf8')
|
11
LEORChn 2019-11-29 02:53:48 +08:00
# 不好意思,刚刚以为代码简化一行之后就没事了,后来发现还是图样
def exec(cmd:str): pip = os.popen(cmd) # 这个地方不能合并一行写,会出错说 read of closed file return pip.buffer.read().decode(encoding='utf8') |
12
mouyong 2020-02-23 12:31:32 +08:00
#11 代码有帮助
|