在python mkdtemp中处理unicode用户名

时间:2015-01-23 00:33:50

标签: python windows python-2.7 unicode python-unicode

我被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)

我有两个问题:

  1. 为什么这应该有用?
  2. 这有多充分证明?从一个类似的问题(见这个答案:Python Popen failing to use proper encoding in Windows PowerShell)我得到了一个概念,我可能应该使用sys.stdout.encoding - 我是否接近标记?
  3. 编辑:实际上是一行:

    print u"input encoding: %s; output encoding: %s; locale: %s" % (
        sys.stdin.encoding,getattr(sys.stdout,'encoding',None),
        locale.getdefaultlocale())
    

    打印

      

    输入编码:无;输出编码:无; locale:('ja_JP','cp932')

    所以也许我应该去locale.getpreferredencoding()(参见例如subprocess.Popen with a unicode path

    建议的评论中的

    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))
    >>> 
    

1 个答案:

答案 0 :(得分:1)

我终于选择了:

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第一次尝试捕获就足够但我留下了追溯,所以我可以获得更多输入;)