Share with unicode usernames in python mkdtemp

I got bitten by http://bugs.python.org/issue1681974 - quoting from there:

mkdtemp fails on Windows if the Windows username has non-ASCII characters such as ä or ö in it. mkdtemp throws an encoding error. It seems to have something to do with Windows defaults to temp dir"c:\documents and settings\<user name>\local settings\temp"

The workaround used by the 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)

      

I have 2 questions:

Edit: actually the line:

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

      

prints

input encoding: no; Output coding: No; locale: ('ja_JP', 'cp932')

so maybe I should go for locale.getpreferredencoding () (see for example subprocess.Popen with unicode path )

Edit2: The comments suggest encoding the prefix in mbcs - unfortunately not an option as the codebase expects unicode all over the place and will hit sooner or later. The outputted code is a simplified snippet.

Edit3 : My little workaround didn't seem to work around anything - will try:

fsenc = sys.getfilesystemencoding() or 'mbcs'
return tempfile.mkdtemp(prefix=prefix.encode(fsenc)).decode(fsenc)

      

if any non-ascii user is left to check.

Meanwhile - the reproducers below don't work for me:

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'

      

and variations ...

edit4 - the directory exists in an absolute sense:

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


source to share


1 answer


Finally I went with:

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 the first try to catch is sufficient, but I left traces behind, so I can get another input;)

+1


source







All Articles