如何在Python 3中读取文件名中带有西里尔字符的文件

时间:2018-02-03 14:36:24

标签: python python-3.x unicode filepath

我正在尝试使用带有西里尔字符的文件名来读取图像文件。

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 个答案:

答案 0 :(得分:2)

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

  

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

     

[...]

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

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

结果,UTF-8数据无法正确解码,出现解码错误,surrogateescape error handler开始播放,并且已经保留了&#39;字节为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')