【问题标题】:Save file with Russian letters in the file name在文件名中保存带有俄语字母的文件
【发布时间】:2016-05-09 03:51:21
【问题描述】:

我有这个 Python 脚本,它获取网页的信息,然后将此信息保存到文本文件中。但是这个文本文件的名字会不时改变,有时会变成西里尔字母,有时会变成韩文。

问题是,如果我尝试使用名称“бореиская”保存文件,那么当我在 Windows 中查看它时,该名称会显得很奇怪。

我猜我需要在某些地方更改一些编码。但是名称正在发送到open() 函数:

server = "бореиская"
file = open("eu_" + server + ".lua", "w")

我之前是从一个已经包含所有名称的数组中获取服务器变量。

但如前所述,在 Windows 中,名称出现时带有一些非常奇怪的字符。

【问题讨论】:

  • 你用的是哪个版本的python? Unicode 字符串在 python2 中应以 u"бореиская" 为前缀,而在 3 中 unicode 是默认值。同样,在从流中读取时,您可以将其编码/解码到/从 utf-8。 Relevant docs
  • 使用 python 2.7,将尝试应用您链接的文档中提到的更改。之前没发现。将返回结果。

标签: python python-2.7 unicode encoding cyrillic


【解决方案1】:

tl;博士

始终使用 Unicode 字符串作为文件名和路径。例如:

io.open(u"myfile€.txt")
os.listdir(u"mycrazydirß")

在你的情况下:

server = u"бореиская"
file = open(u"eu_" + server + ".lua", "w")

我假设server 将来自另一个位置,因此您需要确保它被正确解码为 Unicode 字符串。见io.open()

说明

窗口

Windows 使用 UTF-16 存储文件名。 Windows i/o API 和 Python 隐藏了这一细节,但需要 Unicode 字符串,否则字符串必须使用正确的 8 位代码页。

Linux

文件名可以由任何字节字符串、任何编码组成,只要它不是 ASCII“。”要么 ”..”。由于每个系统用户都可以有自己的编码,因此您确实不能保证一个用户使用的编码与另一个用户相同。 locale 用于配置每个用户的环境。用户的终端编码也需要与编码相匹配才能保持一致。

最好的结果是用户没有更改他们的区域设置,并且所有应用程序都使用相同的区域设置。例如,默认语言环境可能是:en_GB.UTF-8,这意味着文件和文件名的编码应该是 UTF-8。

当 Python 遇到 Unicode 文件名时,它将使用用户的语言环境来解码/编码文件名。编码后的字符串将直接传递给内核,这意味着您可能会幸运地使用“UTF-8”文件名。

操作系统

OS X 的文件名始终采用 UTF-8 编码,无论用户的语言环境如何。因此,文件名应该是 Unicode 字符串,但可以在用户的​​语言环境中编码并进行翻译。由于大多数用户的语言环境是*.UTF-8,这意味着您实际上可以传递 UTF-8 编码的字符串或 Unicode 字符串。

综述

为了获得最佳的跨平台兼容性,请始终使用 Unicode 字符串,因为在大多数情况下它们会被转换为正确的编码。实际上只有 Linux 具有最大的歧义,因为某些应用程序可能会选择忽略默认语言环境,或者用户可能已将其语言环境更改为非 UTF-8 版本。

【讨论】:

  • 感谢您提供的非常好的描述性评论。可悲的是,这对我不起作用。我刚刚得到 UnicodeDecodeError: 'ascii' codec can't decode byte 0xd0 in position 0: ordinal not in range(128) 我什至尝试使用 u"".join(server) 并得到了同样的结果。请注意,我在 python 2.7
  • 如上所述,server 需要是一个 Unicode 对象。你真的应该在输入点解码server。但是,您可以尝试:file = open(u"eu_" + server.decode("utf-8") + ".lua", "w")file = open(u"eu_" + server.decode("cp1251") + ".lua", "w")
  • 您好,抱歉回复晚了,不过最近很忙,还是想学这个。但是仍然出现错误: UnicodeEncodeError: 'ascii' codec can't encode characters in position 0-15: ordinal not in range(128) print "Trying to get:" + server.decode("cp1251") 也尝试使用 .decode ("utf-8")
  • 听起来 server 现在是 Unicode。打印时无需对其进行编码或解码。 print 通过标准输出将自动为您编码为适当的编码。如果您尝试在您所在区域之外打印字符,您将遇到的唯一麻烦是在 Windows 控制台中。然后你必须使用“win-unicode-console”
  • response = urllib2.urlopen(htmlLink.decode("utf-8")) Link cus 我似乎无法从 cmd 复制文本:S puu.sh/mZ4EO/229e2f28c9.png
【解决方案2】:

我正在 Windows 中查看它。 ...使用python 2.7

在 Windows 上使用 Unicode 文件名。 Python 可以在那里使用 Unicode API。

不要在字节串文字中使用非 ascii 字符(Python 3 明确禁止使用)。

  • 使用 Unicode 文字 u'' 或在模块顶部添加 from __future__ import unicode_literals
  • 确保编码声明 (# -*- coding: utf-8 -*-) 正确,即您的 IDE/编辑器使用指定的编码来保存您的 Python 源代码
#!/usr/bin/env python
# -*- coding: utf-8 -*-

server = u"бореиская"
with open(u"eu_{server}.lua".format(**vars()), "w") as file:
    ...

【讨论】:

  • 我什至尝试使用 u"".join(server) 并得到同样的结果。得到:UnicodeDecodeError:'ascii'编解码器无法解码位置 0 的字节 0xd0:序数不在范围内(128)
  • @Thomja : 你明白type(server) 应该是unicode 吗?注意:u"" 创建 Unicode 字符串
  • 但我不能在变量名前添加 u 吗?就像说我有一个名为 test 的变量。我不能做 utest,因为它会尝试找到一个名为 utest 的变量。
  • @Thomja :标题中问题的答案是:使用 Unicode 文件名。如果您不知道什么是 Unicode 或如何在您的特定情况下获取它,请提出一个新问题。很明显,将 u 添加到变量 name 不会将相应的对象转换为 Unicode(您应该得到 NameError: utest is not defined 异常)
【解决方案3】:

在 Windows 中,您可能必须将文件名编码为 cp125x 编码,但我不知道是哪一个 - 可能是 cp1251

filename = "eu_" + server + ".lua"

filename = filename.encode('cp1251')

file = open(filename, 'w')

在 Linux 中你应该使用utf-8

【讨论】:

  • 谢谢,这需要对我的循环进行一些修改。但我会试试这个。我是否也必须对文件的内容执行此操作?
  • 如果您的内容中有俄语字母,您可能也必须进行编码。但也许你需要utf-8 或其他编码。
  • 你不应该这样做(你应该通过 Unicode 代替)而且它无论如何都不会工作。 OP 使用 Python 2.7 和 server 是一个非 ascii 字节串,因此 filename.encode('cp1251') 产生 UnicodeDecodeError: 'ascii' codec can't decode ...
  • 仍然收到奇怪的文字。
  • @furas,在 Windows 上,您应该只为文件路径传递 Unicode——无需编码。在 Linux 上,您不能保证用户的语言环境和终端仿真是基于 UTF-8 的,因此您可能会制作用户无法正确看到的文件名。同样,使用 Unicode。
猜你喜欢
  • 1970-01-01
  • 2014-04-26
  • 2012-04-01
  • 2016-11-10
  • 1970-01-01
  • 1970-01-01
  • 2013-02-02
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多