How to use subprocess popen Python
subprocess.Popen
takes a list of arguments:
from subprocess import Popen, PIPE
process = Popen(['swfdump', '/tmp/filename.swf', '-d'], stdout=PIPE, stderr=PIPE)
stdout, stderr = process.communicate()
There's even a section of the documentation devoted to helping users migrate from os.popen
to subprocess
.
Using python with subprocess Popen
To at least really start the subprocess, you have to tell the Popen-object to really communicate.
def run_command(command):
p = subprocess.Popen(command, shell=True,
stdout=subprocess.PIPE,
stderr=subprocess.STDOUT)
return p.communicate()
How to use subprocess Popen?
Your command
uses pipe |
. It requires a shell:
p = subprocess.Popen(command, shell=True)
The command
itself as far as I can tell looks ok.
How to use the subprocess Popen.communicate() method?
You're not providing any stdout to the Popen constructor, the default functionality simply writes the output to parent's stdout handle. Hence you're seeing it being printed in your shell.
Quoting from Popen
's docs:
With the default settings of
None
, no redirection will occur; the child’s file handles will be inherited from the parent.
To populate stdout in resulting tuple use subprocess.PIPE
as stdout.
Quoting from docs:
To get anything other than
None
in the result tuple, you need to give
stdout=PIPE
and/orstderr=PIPE
too.
>>> import subprocess
>>> p = subprocess.Popen(["echo", "hello"], stdout=subprocess.PIPE)
>>> p.communicate()
('hello\n', None)
How to use subprocess.Popen() instead of os.popen() in Python?
Just use subprocess.Popen
to create a new process, with its stdout redirected to a PIPE, in text mode and then read its stdout.
Python version >= 3.6
from subprocess import Popen, PIPE
with Popen(f'ps {pid}'.split(), stdout=PIPE, text=True) as proc:
pinfo = proc.stdout.readlines()
As you have requested for python2.7, I have given the code. But remember that python2.7 has reached EOL and you should be using python3.x
Python version = 2.7
from subprocess import Popen, PIPE
proc = Popen(f'ps {pid}'.split(), stdout=PIPE)
pinfo = proc.stdout.readlines()
Refer subprocess documentation for more information
What is the difference between subprocess.popen and subprocess.run
subprocess.run()
was added in Python 3.5 as a simplification over subprocess.Popen
when you just want to execute a command and wait until it finishes, but you don't want to do anything else in the mean time. For other cases, you still need to use subprocess.Popen
.
The main difference is that subprocess.run()
executes a command and waits for it to finish, while with subprocess.Popen
you can continue doing your stuff while the process finishes and then just repeatedly call Popen.communicate()
yourself to pass and receive data to your process. Secondly, subprocess.run()
returns subprocess.CompletedProcess
.
subprocess.run()
just wraps Popen
and Popen.communicate()
so you don't need to make a loop to pass/receive data or wait for the process to finish.
Check the official documentation for info on which params subprocess.run()
pass to Popen
and communicate()
.
Run Python script within Python by using `subprocess.Popen` in real time
Last night I've set out to do this using a pipe:
import os
import subprocess
with open("test2", "w") as f:
f.write("""import time
print('start')
time.sleep(2)
print('done')""")
(readend, writeend) = os.pipe()
p = subprocess.Popen(['python3', '-u', 'test2'], stdout=writeend, bufsize=0)
still_open = True
output = ""
output_buf = os.read(readend, 1).decode()
while output_buf:
print(output_buf, end="")
output += output_buf
if still_open and p.poll() is not None:
os.close(writeend)
still_open = False
output_buf = os.read(readend, 1).decode()
Forcing buffering out of the picture and reading one character at the time (to make sure we do not block writes from the process having filled a buffer), closing the writing end when process finishes to make sure read catches the EOF correctly. Having looked at the subprocess
though that turned out to be a bit of an overkill. With PIPE
you get most of that for free and I ended with this which seems to work fine (call read as many times as necessary to keep emptying the pipe) with just this and assuming the process finished, you do not have to worry about polling it and/or making sure the write end of the pipe is closed to correctly detect EOF and get out of the loop:
p = subprocess.Popen(['python3', '-u', 'test2'],
stdout=subprocess.PIPE, bufsize=1,
universal_newlines=True)
output = ""
output_buf = p.stdout.readline()
while output_buf:
print(output_buf, end="")
output += output_buf
output_buf = p.stdout.readline()
This is a bit less "real-time" as it is basically line buffered.
Note: I've added -u
to you Python call, as you need to also make sure your called process' buffering does not get in the way.
How can I use subprocess.Popen in a for loop?
Per @jasonharper's suggestion, I needed to make a new open file object for each iteration.
input_file = Path("input.json")
for thread in threads:
new_env = default_env
new_env["OMP_NUM_THREADS"] = str(thread)
print("Starting run for {} threads".format(thread))
process = subprocess.Popen(
benchmark_command, env=new_env, stdin=input_file.open(), stdout=subprocess.PIPE)
lines = []
for line in process.stdout:
print(line.decode(), end='')
results.append(Result(lines, thread))
print("Completed run for {} threads".format(thread))
Related Topics
Conda Reports Packagesnotfounderror: Python=3.1 for Reticulate Environment
How to Postpone/Defer the Evaluation of F-Strings
How to "Test" Nonetype in Python
How to Construct a Timedelta Object from a Simple String
What's the Difference Between Select_Related and Prefetch_Related in Django Orm
Partial Coloring of Text in Matplotlib
How to Take the First N Items from a Generator or List
":=" Syntax and Assignment Expressions: What and Why
Why Do We Use _Init_ in Python Classes
Computing Cross-Correlation Function
How to Make Separator in Pandas Read_CSV More Flexible Wrt Whitespace, for Irregular Separators
Why Isn't My Pandas 'Apply' Function Referencing Multiple Columns Working
Way to Change Google Chrome User Agent in Selenium
Installing Python Packages from Local File System Folder to Virtualenv with Pip
Is There a Decorator to Simply Cache Function Return Values
Function Not Changing Global Variable
How to Mock an Open Used in a with Statement (Using the Mock Framework in Python)