Python popen2函数重写(php-mail-parsing)

时间:2015-01-23 09:19:48

标签: php python subprocess popen

我尝试将popen2重写为subprocess.Popen。而且我收到了错误。

我的代码:

cmd = '/usr/sbin/sendmail -t -i'
if len(sys.argv) == 3:
  cmd += " -f%s" % sys.argv[2]

# OLD CODE =======================
#(out, s) = popen2(cmd)
#s.write(data)
#s.close()
# ================================

# NEW CODE =======================

p = Popen(cmd, shell=True, stdin=PIPE, stdout=PIPE, close_fds=True)
(out, s) = (p.stdin, p.stdout)
s.write(data)
s.close()
sys.stdout.flush()

在apache error_log中我收到错误:

Traceback (most recent call last):
  File "/opt/php-secure-sendmail/secure_sendmail.py", line 80, in <module>
    s.write(data)
IOError: File not open for writing
sendmail: fatal: test@serve.tld(10000): No recipient addresses found in message header
plesk sendmail[2576]: sendmail unsuccessfully finished with exitcode 75

也许有人知道怎么弄清楚这段代码?

2 个答案:

答案 0 :(得分:0)

你正在尝试写一个只能阅读的stdout。

stdout包含新进程的打印输出,必须写入stdin才能发送数据。

popen2返回一个元组(stdout,stdin),这就是注释代码的工作原理。 https://docs.python.org/2/library/popen2.html

只需反转元组中的顺序即可:

p = Popen(cmd, shell=True, stdin=PIPE, stdout=PIPE, close_fds=True)
(out, s) = (p.stdout, p.stdin)
s.write(data)
s.close()
sys.stdout.flush()

答案 1 :(得分:0)

您可以使用.communicate() methoddata传递给子流程:

cmd = '/usr/sbin/sendmail -t -i'.split()
if len(sys.argv) > 2:
  cmd += ["-f", sys.argv[2]]
p = Popen(cmd, stdin=PIPE, close_fds=True)
p.communicate(data)

请注意,您在这里不需要shell=True

我已删除stdout=PIPE,因为我看不到代码中使用的输出。如果要抑制输出;见How to hide output of subprocess in Python 2.7