Python3 下读取 .txt 文件中文乱码问题如何解决?

基本情况: Vultr $2.5/year, CentOS 7, 安装的是 Python3.6。

@app.route("/douban", methods=['GET'])
def doubanFM():
    f = open('douban.txt', 'r')
    txt = f.read()
    lines = txt.split('#\n')
    lines = lines[:-1]
    return random.choice(lines)

用 Python3.6 运行上面的代码,出现错误。其中,douban.txt 文件中大都为中文字符,.py 文件开头加了 #coding:utf-8。主要错误代码如下:

...
...
File "/usr/lib64/python3.6/site-packages/flask/app.py", line 1612, in full_dispatch_request
    rv = self.dispatch_request()
  File "/usr/lib64/python3.6/site-packages/flask/app.py", line 1598, in dispatch_request
    return self.view_functions[rule.endpoint](**req.view_args)
  File "/root/weather/app.py", line 32, in DoubanFM
    txt = f.read()
  File "/usr/lib64/python3.6/encodings/ascii.py", line 26, in decode
    return codecs.ascii_decode(input, self.errors)[0]
UnicodeDecodeError: 'ascii' codec can't decode byte 0xe6 in position 0: ordinal not in range(128)

后来没办法换用 CentOS 自带的 Python2 运行,没错误,能正常输出中文。但我很想知道为啥用 Python3.6 来运行就不行,求相应解决办法。


Python3 下读取 .txt 文件中文乱码问题如何解决?

25 回复

.py 文件声明的事你脚本的编码方式,和你操作的文件没有关系。

file douban.txt 看一下编码方式。

https://i.loli.net/2017/08/23/599d33d15ced5.png


遇到.txt文件中文乱码,通常是文件编码和读取编码不匹配导致的。直接上代码,最稳的解决方案是先用chardet库检测编码,再用检测到的编码去读取。

首先,安装检测库:

pip install chardet

然后,用这个脚本来读文件:

import chardet

def read_txt_file(file_path):
    # 先用二进制模式读取一部分字节来检测编码
    with open(file_path, 'rb') as f:
        raw_data = f.read(10000)  # 读前10000字节通常足够检测
        result = chardet.detect(raw_data)
        encoding = result['encoding']
        confidence = result['confidence']
        print(f"检测到编码: {encoding} (置信度: {confidence:.2%})")
    
    # 用检测到的编码重新打开文件
    try:
        with open(file_path, 'r', encoding=encoding) as f:
            content = f.read()
        return content
    except UnicodeDecodeError:
        # 如果检测的编码不对,尝试常见的中文编码
        for enc in ['utf-8', 'gbk', 'gb2312', 'gb18030']:
            try:
                with open(file_path, 'r', encoding=enc) as f:
                    content = f.read()
                print(f"使用备用编码 {enc} 成功读取")
                return content
            except UnicodeDecodeError:
                continue
        raise ValueError("无法用常见编码读取文件")

# 使用示例
file_path = 'your_file.txt'
content = read_txt_file(file_path)
print(content[:500])  # 打印前500字符看看

如果不想装chardet,或者知道文件大概是什么编码,可以直接试这几个常见的中文编码:

encodings = ['utf-8', 'gbk', 'gb2312', 'gb18030']
content = None
for enc in encodings:
    try:
        with open('your_file.txt', 'r', encoding=enc) as f:
            content = f.read()
        break
    except UnicodeDecodeError:
        continue
if content:
    print(content)

关键就一点:文件保存的编码和open()里指定的encoding参数必须一致。Windows系统下创建的.txt文件经常是gbk(或gb2312gb18030),而Linux/macOS或现代编辑器默认多是utf-8。用上面代码检测或轮询一遍基本能解决。

总结:用工具检测或手动试常见编码。

‘ascii’ codec can’t decode byte 0xe6

CentOS VPS 上运行结果为:douban.txt: UTF-8 Unicode text

我在 Mac 上用 python3 运行 app.py 没问题,是在 CentOS VPS 用 python3.6 运行中文字符报错。

f = open(‘douban.txt’, ‘r’, encoding="utf-8)
# 试一下

可以的,谢谢~

f.close()

请教下: 如果不关闭文件影响大不大?如果我用 with open(‘douban.txt’, ‘r’, encoding="utf-8) 是不是不用关了

代码执行到 with 范围以外会自己关闭文件

首先, 的答案 +1。

感觉跟我之前遇到的问题类似,我估计你 用 open(‘douban.txt’, ‘r’, encoding="utf-8) 之后,然后 read() 出来数据;我估计你打印(print)的时候也会报错。

你 3.6 自己编译安装的吧? 安装后有升级过 系统的 C 库么?

with 会自动关

print 的时候报不报错取决于终端的使用的编码吧,和代码就没啥关系了吧。

尽量都用 with open… as …来打开文件。

我所指的报错是 python raise Exception。系统遇到打印不出来的字符是会用[乱码]形式展现不会报错。

当 python 无法正确推断 sys.stdout.encoding 时可能会报错,比如它将该 encoding 错误推断成 ascii 就会在最后对 > 127 的字节码 报错。

哈哈哈…最近看来开始折腾 douban 的人增加了

我那时是按照 DO 上的这篇 [文章]( https://www.digitalocean.com/community/tutorials/how-to-install-python-3-and-set-up-a-local-programming-environment-on-centos-7) 在 CentOS 上安装 Python3.6 的,这样可以吗

写个最简单的文件,看看你 VPS 上的 Python3 能不能执行:

python<br>#coding: utf-8<br><br># 中文注释<br>print("中文哟")<br>

不能的话,估计是你 Python3 安装得有问题,建议更换为 pyenv

运行后,确实出错了。我明天重装看看~~

<br>Traceback (most recent call last):<br> File "<a target="_blank" href="http://zz.py" rel="nofollow noopener">zz.py</a>", line 4, in &lt;module&gt;<br> print("\u4e2d\u6587\u54df")<br>UnicodeEncodeError: 'ascii' codec can't encode characters in position 0-2: ordinal not in range(128)<br>

可能跟你 python 安装得方式无关。

也有可能是的 VPS 系统语言设置得不对。用 locale 命令查看下,本地化得设置, 确认是否为 UTF-8(特别是 LC_CTYPE=xxx.UTF-8)。

如果你自己升级过 c 库,就很有可能出问题。这时你可能直接设置不回来 LC_CTYPE=xxx.UTF-8, 可以 参照 https://my.oschina.net/VASKS/blog/659236yum reinstall glibc-common 看看。这个问题我也 hold 不住,各种坑要详细一步步解才行。

最后还有一个简便得解决方案就是,设定 python 的 encoding 的环境变量(PYTHONIOENCODING: Encoding[:errors] used for stdin/stdout/stderr.)。

e.g.

export PYTHONIOENCODING=utf-8

或者 你将此变量保存到 ~/.bashrc 中吧。

文件失效了?

谢谢回复。

1、locale 后返回都是 UTF-8 ;
2、c 库我没明确升级过。VPS 较新,只装 oneinstack,不知道对 c 库有没有影响;
3、设置并保存 ~/.bashrc 后,可以了 😄

回到顶部