TypeError: execv() arg 2 must contain only strings (subprocess and unicode)
TypeError: execv() arg 2 must contain only strings (subprocess and unicode)
我有这个 Python2.7 脚本,如果 LANG != 'C':
# -*- coding: utf-8 -*-
from __future__ import absolute_import, division, unicode_literals, print_function
import os
import subprocess
import sys
print('LANG: {}'.format(os.environ['LANG']))
print('sys.getdefaultencoding(): {}'.format(sys.getdefaultencoding()))
print('sys.getfilesystemencoding(): {}'.format(sys.getfilesystemencoding()))
subprocess.check_call(['echo', 'Umlauts üöä'])
拜访 linux shell:
user@host:~$ python src/execv-arg-2-must-contain-only-strings.py
LANG: de_DE.UTF-8
sys.getdefaultencoding(): ascii
sys.getfilesystemencoding(): UTF-8
Umlauts üöä
但这失败了:
user@host:~$ LANG=C python src/execv-arg-2-must-contain-only-strings.py
LANG: C
sys.getdefaultencoding(): ascii
sys.getfilesystemencoding(): ANSI_X3.4-1968
Traceback (most recent call last):
File "src/execv-arg-2-must-contain-only-strings.py", line 12, in <module>
subprocess.check_call(['echo', 'Umlauts üöä'])
File "/usr/lib/python2.7/subprocess.py", line 536, in check_call
retcode = call(*popenargs, **kwargs)
File "/usr/lib/python2.7/subprocess.py", line 523, in call
return Popen(*popenargs, **kwargs).wait()
File "/usr/lib/python2.7/subprocess.py", line 711, in __init__
errread, errwrite)
File "/usr/lib/python2.7/subprocess.py", line 1343, in _execute_child
raise child_exception
TypeError: execv() arg 2 must contain only strings
如何使此脚本在 Python2.7 上使用 LANG=C 运行?
我没有 post 它作为答案,因为我没有办法在 atm 上检查它的正确性。但原则上,如果你想将数据作为 subprocess/shell 参数发送,你必须匹配所述数据的编码(然后在接收子进程中将其解码)否则 Python 不知道如何打包参数。
因此,如果您正在使用 utf-8
文字(在您的编码 header 中定义)并且您想要将其发送到子进程,您应该首先将其解码为 native unicode object,然后将其编码为系统对当前环境的编码,例如:
literal_argument = "Umlauts üöä" # string literal
unicode_argument = literal_argument.decode("utf-8") # unicode
encoded_argument = unicode_argument.encode(sys.getdefaultencoding()) # sys encoded
subprocess.check_call(['echo', encoded_argument])
虽然更安全,但它仍然可以在 non-standard shell 秒时中断。在可能的情况下,使用子进程的 STDIN 管道将不适合当前 shell 的数据作为参数传递 - 那么您不必担心不同的代码页,只要两个进程就编码方式达成一致使用.
使用LANG=C.UTF-8代替LANG=C
user@host> LANG=C.UTF-8 python t.py
LANG: C.UTF-8
sys.getdefaultencoding(): ascii
sys.getfilesystemencoding(): UTF-8
Umlauts üöä
:-)
我有这个 Python2.7 脚本,如果 LANG != 'C':
# -*- coding: utf-8 -*-
from __future__ import absolute_import, division, unicode_literals, print_function
import os
import subprocess
import sys
print('LANG: {}'.format(os.environ['LANG']))
print('sys.getdefaultencoding(): {}'.format(sys.getdefaultencoding()))
print('sys.getfilesystemencoding(): {}'.format(sys.getfilesystemencoding()))
subprocess.check_call(['echo', 'Umlauts üöä'])
拜访 linux shell:
user@host:~$ python src/execv-arg-2-must-contain-only-strings.py
LANG: de_DE.UTF-8
sys.getdefaultencoding(): ascii
sys.getfilesystemencoding(): UTF-8
Umlauts üöä
但这失败了:
user@host:~$ LANG=C python src/execv-arg-2-must-contain-only-strings.py
LANG: C
sys.getdefaultencoding(): ascii
sys.getfilesystemencoding(): ANSI_X3.4-1968
Traceback (most recent call last):
File "src/execv-arg-2-must-contain-only-strings.py", line 12, in <module>
subprocess.check_call(['echo', 'Umlauts üöä'])
File "/usr/lib/python2.7/subprocess.py", line 536, in check_call
retcode = call(*popenargs, **kwargs)
File "/usr/lib/python2.7/subprocess.py", line 523, in call
return Popen(*popenargs, **kwargs).wait()
File "/usr/lib/python2.7/subprocess.py", line 711, in __init__
errread, errwrite)
File "/usr/lib/python2.7/subprocess.py", line 1343, in _execute_child
raise child_exception
TypeError: execv() arg 2 must contain only strings
如何使此脚本在 Python2.7 上使用 LANG=C 运行?
我没有 post 它作为答案,因为我没有办法在 atm 上检查它的正确性。但原则上,如果你想将数据作为 subprocess/shell 参数发送,你必须匹配所述数据的编码(然后在接收子进程中将其解码)否则 Python 不知道如何打包参数。
因此,如果您正在使用 utf-8
文字(在您的编码 header 中定义)并且您想要将其发送到子进程,您应该首先将其解码为 native unicode object,然后将其编码为系统对当前环境的编码,例如:
literal_argument = "Umlauts üöä" # string literal
unicode_argument = literal_argument.decode("utf-8") # unicode
encoded_argument = unicode_argument.encode(sys.getdefaultencoding()) # sys encoded
subprocess.check_call(['echo', encoded_argument])
虽然更安全,但它仍然可以在 non-standard shell 秒时中断。在可能的情况下,使用子进程的 STDIN 管道将不适合当前 shell 的数据作为参数传递 - 那么您不必担心不同的代码页,只要两个进程就编码方式达成一致使用.
使用LANG=C.UTF-8代替LANG=C
user@host> LANG=C.UTF-8 python t.py
LANG: C.UTF-8
sys.getdefaultencoding(): ascii
sys.getfilesystemencoding(): UTF-8
Umlauts üöä
:-)