Python 子进程标准输入=subprocess.PIPE 和 unicode

Python subprocess stdin=subprocess.PIPE and unicode

好的,一些背景故事。我正在为我的应用程序编写备份和恢复功能。我想允许他们的备份文件的加密密码允许任何 unicode 字符。然后我不得不使用 subprocess 来实际 运行 备份命令,它可以正常使用:

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 实例时。这些都不起作用。

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

好的...我现在将停止子进程上的私刑。在 python 2.

中混合使用 unicode 和 str 类型完全是我的错误

将列表传递给 check_call() 命令时,似乎有一些功能可以在向 os 发出命令之前对所有 unicode 进行编码。使用 communicate() 时,它需要一个字符串,但是将列表中的 unicode 和 str 类型的混合传递给 str 类型 .join 操作,它依赖于 pythons 'helpful' 组合操作,默认为使用 '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。