【问题标题】:How to read file with cyrillic characters in the filename in Python 3如何在 Python 3 中读取文件名中带有西里尔字符的文件
【发布时间】:2018-02-03 14:36:23
【问题描述】:

我正在尝试读取文件名包含西里尔字符的图像文件。

ls /home/atin/test
ОД Д.bmp

现在我正在尝试在 python 3 中读取“ОД Д.bmp”

image_path='/home/atin/test/ОД Д.bmp'
import matplotlib.pyplot as plt
sample_image=plt.imread(image_path)

但我收到此错误。

SystemError: <built-in function read_png> returned NULL without setting an error

os.listdir('/home/atin/test') 给出以下输出

['\udcd0\udc9e\udcd0\udc94\udcd0\udc94.bmp']

如何将上述输出解码为原始文件名 ОД Д.bmp。 我在这里在 ubuntu 中使用 python 3.6。

【问题讨论】:

  • ОД р1ОД Д 不同。该错误不会立即向我表明文件名是这里的问题。
  • sys.getfilesystemencoding() 返回什么?这可能是一个错误的值。这是什么操作系统?
  • 那些\u 转义序列是低代理点。这可能表明文件系统编码不是 UTF-8,但 Python 需要 UTF-8。然后通过 surrogateescape 错误处理程序保留字节,但这意味着原始数据是 b'\xd0\x9e\xd0\x94 \xd0\x94.bmp',这是 有效的 UTF-8
  • 我已经进行了必要的编辑,很抱歉输入错误。但错误仍然是一样的。
  • UNIX 命令locale 产生什么?对于给定的文件系统,这几乎肯定是错误的。

标签: python python-3.x unicode filepath


【解决方案1】:

您的系统配置了错误的区域设置。在 Linux 上,Python 从语言环境中获取文件系统编解码器。来自sys.getfilesystemencoding() documentation

返回用于在 Unicode 文件名和字节文件名之间进行转换的编码名称。

[...]

  • 在 Unix 上,编码是语言环境编码。

您有一个使用 UTF-8 的文件系统,但 Python 没有正确读取数据。

因此,UTF-8 数据无法正确解码,出现解码错误,surrogateescape error handler 启动,并将字节“保留”为low surrogate codepoints

您可以通过使用相同的错误处理程序编码为 UTF-8 来扭转问题:

>>> '\udcd0\udc9e\udcd0\udc94 \udcd0\udc94.bmp'.encode('utf8', 'surrogateescape')
b'\xd0\x9e\xd0\x94 \xd0\x94.bmp'

结果恰好是您文件名的正确 UTF-8 编码:

>>> '\udcd0\udc9e\udcd0\udc94 \udcd0\udc94.bmp'.encode('utf8', 'surrogateescape').decode('utf8')
'ОД Д.bmp'

您至少需要使用LC_CTYPE=en_US.UTF-8 ,以避免此问题。在您的情况下,您似乎拥有LC_CTYPE=UTF-8,这是无效的(您可以改用LC_CTYPE=en_SG.UTF-8)。

另一种解决方法是使用 bytes 路径:

image_path = '/home/atin/test/ОД Д.bmp'.encode('utf8')

【讨论】:

  • 非常感谢,但是image_path = '/home/atin/test/ОД Д.bmp'.encode('utf8') 仍然不起作用,我收到错误SystemError: &lt;built-in function read_png&gt; returned NULL without setting an error
  • @AtinGhosh:大概然后plt.imread() 再次解码路径。
  • 对不起,实际上image_path = '/home/atin/test/ОД Д.bmp'.encode('utf8') 有效,但是当我尝试plt.imread('/home/atin/test/ОД Д.bmp'.encode('utf8')) 时,它会抛出上述错误。
  • 我试过这个plt.imread("b'/home/atin/test/\xd0\x9e\xd0\x94 \xd0\x94.bmp'"),然后我得到以下错误。 UnicodeEncodeError: 'ascii' codec can't encode characters in position 18-21: ordinal not in range(128)
  • @AtinGhosh:你不应该在它周围加上引号。它应该是plt.imread(b'/home/atin/test/\xd0\x9e\xd0\x94 \xd0\x94.bmp')。但我们已经确定这是行不通的。
猜你喜欢
  • 2021-06-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-09-10
  • 2016-01-13
相关资源
最近更新 更多