unicode_argv.py 1.7 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879
  1. """Get Unicode argv strings in Python 2 on Windows
  2. get_full_unicode_argv based on
  3. http://code.activestate.com/recipes/572200/
  4. argv_setter_hook based on
  5. https://mail.python.org/pipermail/python-list/2016-June/710183.html
  6. """
  7. import sys
  8. from ctypes import WinDLL, c_int, POINTER, byref
  9. from ctypes.wintypes import LPCWSTR, LPWSTR
  10. kernel32 = WinDLL("kernel32", use_last_error=True)
  11. shell32 = WinDLL("shell32", use_last_error=True)
  12. GetCommandLineW = kernel32.GetCommandLineW
  13. GetCommandLineW.argtypes = ()
  14. GetCommandLineW.restype = LPCWSTR
  15. CommandLineToArgvW = shell32.CommandLineToArgvW
  16. CommandLineToArgvW.argtypes = (LPCWSTR, POINTER(c_int))
  17. CommandLineToArgvW.restype = POINTER(LPWSTR)
  18. LocalFree = kernel32.LocalFree
  19. def get_full_unicode_argv():
  20. cmd = GetCommandLineW()
  21. argc = c_int(0)
  22. argv = CommandLineToArgvW(cmd, byref(argc))
  23. py_argv = [arg for i, arg in zip(range(argc.value), argv)]
  24. LocalFree(argv)
  25. return py_argv
  26. def get_unicode_argv():
  27. if original_argv == [""]:
  28. return [u""]
  29. new_argv = get_full_unicode_argv()[-len(original_argv):]
  30. if original_argv[0] == "-c":
  31. new_argv[0] = u"-c"
  32. return new_argv
  33. original_argv = None
  34. def argv_setter_hook(path):
  35. global original_argv
  36. if original_argv is not None: # already got it
  37. raise ImportError
  38. try:
  39. original_argv = sys.argv
  40. except AttributeError:
  41. pass
  42. else:
  43. enable()
  44. finally:
  45. raise ImportError
  46. def enable():
  47. global original_argv
  48. if original_argv is None:
  49. try:
  50. original_argv = sys.argv
  51. except AttributeError: # in sitecustomize in Python 2
  52. sys.path_hooks[:0] = [argv_setter_hook]
  53. return
  54. sys.argv = get_unicode_argv()
  55. def disable():
  56. if original_argv is not None:
  57. sys.argv = original_argv