I'm using subprocess to run a command line program from a Python (3.5.2) script, which I am running in a Jupyter notebook. The subprocess takes a long time to run and so I would like its stdout to be printed live to the screen in the Jupyter notebook.
I can do this no problem in a normal Python script run from the terminal. I do this using:
def run_command(cmd): from subprocess import Popen, PIPE import shlex with Popen(shlex.split(cmd), stdout=PIPE, bufsize=1, universal_newlines=True) as p: for line in p.stdout: print(line, end='') exit_code = p.poll() return exit_code
However, when I run the script in a Jupyter notebook, it does not print the stdout live to the screen. Instead, it prints everything after the subprocess has finished running.
Does anyone have any ideas on how to remedy this?
Many thanks, Johnny
To capture the output of the subprocess. run method, use an additional argument named “capture_output=True”. You can individually access stdout and stderr values by using “output. stdout” and “output.
The Jupyter Notebook has an option to export the notebook to many formats. It can be accessed by clicking File -> Download as -> PDF via LaTeX (or PDF via HTML - not visible in the screenshot).
Capturing Output With %%capture IPython has a cell magic, %%capture , which captures the stdout/stderr of a cell. With this magic you can discard these streams or store them in a variable.
stdout=PIPE means that subprocess' stdout is redirected to a pipe that you should read e.g., using process.communicate() to read all at once or using process.stdout object to read via a file/iterator interfaces.
The ipython notebook has it's own support for running shell commands. If you don't need to capture with subprocess stuff you can just do
cmd = 'ls -l' !{cmd}
Output from commands executed with ! is automatically piped through the notebook.
If you set stdout = None
(this is the default, so you can omit the stdout
argument altogether), then your process should write its output to the terminal running your IPython notebook server.
This happens because the default behavior is for subprocess to inherit from the parent file handlers (see docs).
Your code would look like this:
from subprocess import Popen, PIPE import shlex def run_command(cmd): p = Popen(shlex.split(cmd), bufsize=1, universal_newlines=True) return p.poll()
This won't print to the notebook in browser, but at least you will be able to see the output from your subprocess asynchronously while other code is running.
Hope this helps.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With