【发布时间】:2015-03-21 23:27:42
【问题描述】:
我被http://bugs.python.org/issue1681974 咬了——引自那里:
如果 Windows 用户名中包含任何非 ASCII 字符(如 ä 或 ö),则 mkdtemp 在 Windows 上会失败。 mkdtemp 引发编码错误。这似乎是因为 Windows 中的默认临时目录是
"c:\documents and settings\<user name>\local settings\temp"
OP 使用的解决方法是:
try: # workaround for http://bugs.python.org/issue1681974
return tempfile.mkdtemp(prefix=prefix)
except UnicodeDecodeError:
tempdir = unicode(tempfile.gettempdir(), 'mbcs')
return tempfile.mkdtemp(prefix=prefix, dir=tempdir)
我有两个问题:
- 为什么这应该有效?
- 这个证据有多充分?从类似的问题(请参阅此答案:Python Popen failing to use proper encoding in Windows PowerShell)我得到了我可能应该使用
sys.stdout.encoding的想法 - 我是否接近标记?
编辑:实际上是一行:
print u"input encoding: %s; output encoding: %s; locale: %s" % (
sys.stdin.encoding,getattr(sys.stdout,'encoding',None),
locale.getdefaultlocale())
打印
输入编码:无;输出编码:无;语言环境:('ja_JP', 'cp932')
所以也许我应该使用 locale.getpreferredencoding()(例如参见 subprocess.Popen with a unicode path)
Edit2: 在 cmets 中,建议我在 mbcs 中编码前缀 - 不幸的是,这不是一个选项,因为代码库期望 unicode 无处不在,迟早会爆炸。发布的代码是一个简化的片段。
Edit3:我的小解决方法显然没有解决任何问题 - 将尝试:
fsenc = sys.getfilesystemencoding() or 'mbcs'
return tempfile.mkdtemp(prefix=prefix.encode(fsenc)).decode(fsenc)
如果还有非 ascii 用户可以测试的话。
同时 - 下面的复制器不适合我:
C:\_\Python27\python.exe -u C:\__\JetBrains\PyCharm 3.4.1\helpers\pydev\pydevconsole.py 18324 18325
PyDev console: starting.import sys; print('Python %s on %s' % (sys.version, sys.platform))
Python 2.7.8 (default, Jun 30 2014, 16:03:49) [MSC v.1500 32 bit (Intel)] on win32
sys.path.extend(['C:\\Dropbox\\eclipse_workspaces\\python\\wrye-bash'])
>>> d = u'ελληνικα'.encode(sys.getfilesystemencoding()); os.environ['TEMP'] = os.path.abspath(d)
>>> import tempfile; tempfile.mkdtemp(prefix=u'x')
u'c:\\users\\mrd\\appdata\\local\\temp\\xtf3nav'
还有变体……
edit4 - 目录绝对存在:
>>> d = u'ελληνικα'.encode(sys.getfilesystemencoding()); os.path.abspath(d)
'C:\\Dropbox\\eclipse_workspaces\\python\\wrye-bash\\e??????a'
>>> assert os.path.isdir(os.path.abspath(d))
Traceback (most recent call last):
File "<input>", line 1, in <module>
AssertionError
>>> d = u'ελληνικα'
>>> os.path.abspath(d)
u'C:\\Dropbox\\eclipse_workspaces\\python\\wrye-bash\\\u03b5\u03bb\u03bb\u03b7\u03bd\u03b9\u03ba\u03b1'
>>> assert os.path.isdir(os.path.abspath(d))
>>>
【问题讨论】:
-
@eryksun:他们在 bug 中讨论了这个问题 - 问题在于用户名 - mbsc 的证据有多充分 - 它对日本用户有用吗?
-
不,这不仅仅是用户名,因为
os.path.join不会引发UnicodeDecodeError,除非您将非ASCIIstr与unicode混合使用。在这种情况下,如果prefix是unicode,就会发生这种情况。 -
'mbcs'使用 WindowsMultiByteToWideChar(解码)和WideCharToMultiByte(编码)实现CP_ACP编码(系统 ANSI 编码),这是locale.getpreferredencoding()返回的内容。也就是说,当涉及到未定义的字符时,'cp932'的 Python 编解码器可能比 Windows 更严格。我知道'cp1252'就是这种情况,'\x81'.decode('cp1252')会失败,而'\x81'.decode('mbcs') == u'\x81'会失败。 -
问题被标记为“过期”。如果您在 Python 2.7 上看到失败;请在错误跟踪器上留言。
-
@J.F.Sebastian: 完成
标签: python windows python-2.7 unicode python-unicode