skip to Main Content

i try to rewrite popen2 to subprocess.Popen. And I get error.

My code:

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()

In apache error_log I get error:

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: [email protected](10000): No recipient addresses found in message header
plesk sendmail[2576]: sendmail unsuccessfully finished with exitcode 75

Maybe somebody has idea how figure out this code?

2

Answers


  1. You’re trying to write on stdout which is open only for reading.

    stdout contains the printed output of the new process, you must write to stdin to send it data.

    popen2 is returning a tuple (stdout, stdin), that’s why the commented code works.
    https://docs.python.org/2/library/popen2.html

    Just invert the order in your tuple and it will work:

    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()
    
    Login or Signup to reply.
  2. You could use .communicate() method to pass data to the child process:

    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)
    

    Notice that you don’t need shell=True here.

    I’ve removed stdout=PIPE because I don’t see the output used in your code. If you want to suppress the output; see How to hide output of subprocess in Python 2.7.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search