在 python mkdtemp 中处理 unicode 用户名
Deal with unicode usernames in python mkdtemp
我被 http://bugs.python.org/issue1681974 咬了 - 从那里引用:
mkdtemp fails on Windows if Windows user name has any non-ASCII characters, like ä or ö, in it. mkdtemp throws an encoding error. This seems to be because the default temp dir in Windows is "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())
打印
input encoding: None; output encoding: None; locale: ('ja_JP', 'cp932')
所以也许我应该选择 locale.getpreferredencoding()(例如参见 [=22=])
Edit2: 在评论中建议我在 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))
>>>
我终于选择了:
sys_fs_enc = sys.getfilesystemencoding() or 'mbcs'
@staticmethod
def tempDir(prefix=None):
try: # workaround for http://bugs.python.org/issue1681974 see there
return tempfile.mkdtemp(prefix=prefix)
except UnicodeDecodeError:
try:
traceback.print_exc()
print 'Trying to pass temp dir in...'
tempdir = unicode(tempfile.gettempdir(), sys_fs_enc)
return tempfile.mkdtemp(prefix=prefix, dir=tempdir)
except UnicodeDecodeError:
try:
traceback.print_exc()
print 'Trying to encode temp dir prefix...'
return tempfile.mkdtemp(
prefix=prefix.encode(sys_fs_enc)).decode(sys_fs_enc)
except:
traceback.print_exc()
print 'Failed to create tmp dir, Bash will not function ' \
'correctly.'
Apparently 第一个 try catch 就足够了,但我留下了回溯,这样我可以获得更多输入;)
我被 http://bugs.python.org/issue1681974 咬了 - 从那里引用:
mkdtemp fails on Windows if Windows user name has any non-ASCII characters, like ä or ö, in it. mkdtemp throws an encoding error. This seems to be because the default temp dir in Windows is
"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())
打印
input encoding: None; output encoding: None; locale: ('ja_JP', 'cp932')
所以也许我应该选择 locale.getpreferredencoding()(例如参见 [=22=])
Edit2: 在评论中建议我在 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))
>>>
我终于选择了:
sys_fs_enc = sys.getfilesystemencoding() or 'mbcs'
@staticmethod
def tempDir(prefix=None):
try: # workaround for http://bugs.python.org/issue1681974 see there
return tempfile.mkdtemp(prefix=prefix)
except UnicodeDecodeError:
try:
traceback.print_exc()
print 'Trying to pass temp dir in...'
tempdir = unicode(tempfile.gettempdir(), sys_fs_enc)
return tempfile.mkdtemp(prefix=prefix, dir=tempdir)
except UnicodeDecodeError:
try:
traceback.print_exc()
print 'Trying to encode temp dir prefix...'
return tempfile.mkdtemp(
prefix=prefix.encode(sys_fs_enc)).decode(sys_fs_enc)
except:
traceback.print_exc()
print 'Failed to create tmp dir, Bash will not function ' \
'correctly.'
Apparently 第一个 try catch 就足够了,但我留下了回溯,这样我可以获得更多输入;)