在supervisord下运行subprocess失败
我有一个用Python写的脚本,它可以发送邮件,运行得很好。当我通过SSH连接到服务器并从命令行运行这个脚本时,一切都正常。输出结果也是一样的,当然没有错误,返回值是0。
evalue = -1
try:
f = tempfile.TemporaryFile()
f.write(body.encode('utf-8'))
f.seek(0)
log.debug("'%s'" % "' '".join(call))
for s in call:
log.debug(type(s))
evalue = subprocess.check_call(call, stdin=f)
except Exception as e:
log.exception(e)
finally:
f and f.close()
f = None
log.debug("evalue %s" % evalue)
我看到的输出是:
mailer_v1 : DEBUG 'mailx' '-s' 'test ñññ ' '-a' '/tmp/test_ñññ_0,00_E.pdf' '-r' 'test <code@nebulo.se>' 'test@nebulo.se'
: DEBUG <type 'str'>
mailer_v1 : DEBUG <type 'str'>
mailer_v1 : DEBUG <type 'unicode'>
mailer_v1 : DEBUG <type 'str'>
mailer_v1 : DEBUG <type 'unicode'>
mailer_v1 : DEBUG <type 'str'>
mailer_v1 : DEBUG <type 'unicode'>
mailer_v1 : DEBUG <type 'unicode'>
mailer_v1 : ERROR execv() arg 2 must contain only strings
Traceback (most recent call last):
File "/data/workers/mailer_v1", line 90, in <module>
evalue = subprocess.check_call(call, stdin=f)
File "/usr/lib/python2.7/subprocess.py", line 506, in check_call
retcode = call(*popenargs, **kwargs)
File "/usr/lib/python2.7/subprocess.py", line 493, in call
return Popen(*popenargs, **kwargs).wait()
File "/usr/lib/python2.7/subprocess.py", line 679, in __init__
errread, errwrite)
File "/usr/lib/python2.7/subprocess.py", line 1259, in _execute_child
raise child_exception
TypeError: execv() arg 2 must contain only strings
mailer_v1 : DEBUG evalue -1
在命令行中,语言环境设置为es_ES.UTF-8,而在supervisord的配置文件中,我有:
environment=LC_ALL=es_ES.UTF-8
谢谢。
1 个回答
1
我可以通过在C语言环境下运行你的脚本来重现你遇到的问题:
$ LANG=C python run-subprocess.py
# -> TypeError: execv() arg 2 must contain only strings
在这种情况下,所有的编码都是ascii格式:
import locale
import sys
print(sys.getfilesystemencoding()) # <-- this is used for args
print(sys.stdout.encoding)
print(locale.getpreferredencoding(False))
print(locale.getpreferredencoding(True))
如果你强制使用utf-8
编码,那么它就能正常工作:
#!/usr/bin/env python
# -*- coding: utf-8 -*-
from subprocess import check_call
cmd = [b'-s', u'test ñññ ', b'-a', u'/tmp/test_ñññ_0,00_E.pdf', b'-r', u'test']
encoding = 'utf-8' # force utf-8 no matter what
# `sys.getfilesystemencoding()` or
# `locale.getpreferredencoding(True)` say
check_call(['echo'] + [s.encode(encoding) if isinstance(s, unicode) else s
for s in cmd])