Python子进程stdin = subprocess.PIPE和unicode

时间:2015-12-09 16:55:55

标签: python unicode utf-8 subprocess

好的,有点背影。我正在为我的应用编写备份和恢复功能。我想允许其备份文件的加密密码允许任何unicode字符。然后我被限制使用子进程来实际运行备份命令,这可以正常使用:

cmd = ['sudo', CMD_SCRIPT, 'python', script, 'backup', password, backup_to]    
subprocess.check_call(cmd)

我已经能够使用相同的unicode密码解密文件,它似乎工作得很好

我的问题出现在恢复阶段;因为恢复过程取消了用于与客户交互的服务器,我需要在单独的守护程序中启动此过程。我完成此任务的代码如下:

cmd = ['python', script, 'restore', password, backup_file, 'user']
proc = subprocess.Popen(['at', 'now'], stdin=subprocess.PIPE)
proc.communicate(' '.join(cmd))

当subprocess.PIPE尝试写入这段代码时(不是我的,可以在subprocess.communicate中找到):

if self.stdin:
    if input:
        try:
            self.stdin.write(input)  # < HERE
        except IOError as e:
            if e.errno != errno.EPIPE and e.errno != errno.EINVAL:
                raise
    self.stdin.close()

它无法引发UnicodeEncodeError:

'ascii' codec can't encode character u'\xdc' in position 66: ordinal not in range(128)

我试过设置proc.stdin.encoding ='utf-8',但它告诉我这个属性是只读的,我在初始化时也试过设置env = {'PYTHONIOENCODING':'utf-8'}我的Popen实例。这些都没有奏效。

是否有我可以使用的另一个stdin对象允许我定义编码?请帮忙。

1 个答案:

答案 0 :(得分:1)

好的......我现在将暂停子进程中的lynch mob。在python 2中混合使用unicode和str类型时,这完全是我的不小心。

将一个列表传递给check_call()命令时,似乎有一些功能可以在向os发出命令之前对所有unicode进行编码。当使用communic()时,它需要一个字符串,但是将列表中的unicode和str类型混合传递给str类型.join操作它依赖于pythons'有用'的组合操作,默认使用'ascii'进行编码和解码作为编解码器。 当我更改代码时,确保列表中的所有内容都是unicode,然后在传递它时对其进行编码,以便按预期方式进行通信。确保我的脚本,密码和backup_file变量为unicode类型后,我的代码现在看起来像:

cmd = [u'python', script, u'restore', password, backup_file, u'user']
proc = subprocess.Popen(['at', 'now'], stdin=subprocess.PIPE)
proc.communicate(u' '.join(cmd).encode('utf-8'))

注意我的字符串的'u'前缀,然后当我传递字符串进行通信时,我能够将自己的编码定义为utf-8。