我对open
有点困惑。我正在运行Windows 10,当我致电sys.getfilesystemencoding
时,我得到mbcs
所以如果我将文件名传递给open
,例如:
open('Meow!.txt')
据说,源文件的编码是utf-8。 open
是否使用设置为默认Windows ANSI代码页的'Meow!.txt'
编码对文件名mbcs
进行编码?然后将请求传递给操作系统?
一般来说,当您将文件名作为2.X中的unicode和3.X中的open
传递给str
时会发生什么?
当文件名作为3.X中的bytes
对象或2.X中的str
传递时,是否为真,会覆盖文件名的默认自动编码?
答案 0 :(得分:1)
以下是在2.7中使用内置open
时内部发生的事情:
Python设置一个常量来命名文件名的默认编码,这个常量称为Py_FileSystemDefaultEncoding
,并且每个平台都有所不同。最终,当其值设置为Null时,Python将尝试获取平台的默认编码,如果有的话:
/*bltinmodule.c*/
/* The default encoding used by the platform file system APIs
Can remain NULL for all platforms that don't have such a concept
*/
#if defined(MS_WINDOWS) && defined(HAVE_USABLE_WCHAR_T)
const char *Py_FileSystemDefaultEncoding = "mbcs";
#elif defined(__APPLE__)
const char *Py_FileSystemDefaultEncoding = "utf-8";
#else
const char *Py_FileSystemDefaultEncoding = NULL; /* use default */
#endif
Py_FileSystemDefaultEncoding
使用“mbcs”(多字节字符集)Windows编码,您可以使用Py_FileSystemDefaultEncoding
调用来检查sys.getfilesystemencoding()
的值:
Python 2.7文档:
sys.getfilesystemencoding()
在Windows NT +上,文件名本身是Unicode,因此不会执行任何转换。
getfilesystemencoding()
仍返回'mbcs',因为这是应用程序在明确要将Unicode字符串转换为用作文件名时等效的字节字符串时应使用的编码。
所以例如我们假设一个带有中文字符的文件名,为简单起见,我将使用U + 5F08中国象棋CJK作为我要写的文件名:
>>> f = open(u'\u5F08.txt', 'w')
>>> f
<open file u'\u5f08', mode 'w' at 0x000000000336B1E0>
open
传递给str
时会发生什么?这个答案取决于平台。例如,在Windows中,不需要将Unicode字符串转换为任何编码,即使使用默认文件系统编码“mbcs”也不需要,以证明:
>>> f = open(u'\u5F08.txt'.encode('mbcs'), 'w')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
IOError: [Errno 22] invalid mode ('w') or filename: '?.txt'
顺便说一句,即使您使用'utf-8'编码,也无法获得正确的文件名:
>>> f = open(u'\u5F08.txt'.encode('utf8'), 'w')
如果您在Windows上检查而不是弈.txt ,这将为您提供å¼.txt文件名。总之,显然没有转换Unicode文件名。我认为此规则也适用于str
。由于2.X中的str
是原始字节字符串,因此Python不会神奇地选择编码**但我无法验证这一点,并且Python可能会使用“mbcs”编码解码str
。通过使用“mbcs”代码页字符集之外的字符可以验证我是否相信,但这又取决于您的Windows语言环境设置。在Windows实现中封装了较低级别。如果内存服务,我认为“mbcs”现在被认为是Windows API的遗产。 Python 3.6使用UTF-8,除非启用了传统模式。
实际上,似乎问题深入到了Windows API及其实现,而不是Python本身的实现。