为什么我的stdin重定向('<')无法与subprocess.Popen()一起使用?

时间:2019-06-04 20:04:13

标签: python-3.x bash

我正在用python构建脚本,其中一部分需要发送包含文件作为邮件正文的电子邮件。脚本不发送文件内容,而是向我发送输入到终端的下一个字符,例如如果我将c作为“ cat”的一部分输入,它不会将c放入终端,而是向我发送一封电子邮件,其中以“ c”作为正文。

这是在CentOS 7.6.1810和Python 3.5.6上。

#!/usr/src/Python-3.5.6/python
import subprocess
import sys
import os

subprocess.Popen(["mail", "-s", "Test Subject", "myemail@myemail.com", "<", "/path/to/file.txt"], stdout=open('stdout', 'w'), stderr=open('errout', 'w'))

file.txt的内容应作为正文发送,但无论输入的是下一个字母,我都会得到它的第一个字母。此后,“ stdout”读取为“ EOT”,并且没有任何内容打印到“ errout”。为了清楚起见,我正在尝试调用命令

mail -s "Test Subject" myemail@myemail.com < /path/to/file.txt

在脚本内部。该命令在Python脚本之外可以正常工作,但是在其中却遇到了问题。

1 个答案:

答案 0 :(得分:3)

subprocess.Popen()默认情况下直接执行新过程。因此,您的代码会将其他一些参数</path/to/file.txt传递给mail可执行文件,这不会产生预期的结果。

在Unix系统上,像<这样的重定向是由Shell处理的,而不是由每个可执行文件处理的。这就是为什么您希望subprocess.Popen()在所有mail参数和mail重定向中在外壳程序中运行< /path/to/file.txt命令的原因。

您可以使用shell=True参数来完成此操作:

subprocess.Popen(["mail", "-s", "Test Subject", "myemail@myemail.com", "<", "/path/to/file.txt"], stdout=open('stdout', 'w'), stderr=open('errout', 'w'), shell=True)

请注意,shell可能不是必需的–您可以Popen打开文件并将mail的{​​{1}}连接到该描述符,请参阅下面的anishsane注释。

应避免使用外壳程序,尤其是在将用户数据传递给子进程的情况下,因为需要对其进行适当的清理以防止命令注入攻击。

请参见Python 3 docs on subprocess.Popen