Asked  7 Months ago    Answers:  5   Viewed   27 times

To launch programs from my Python-scripts, I'm using the following method:

def execute(command):
    process = subprocess.Popen(command, shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
    output = process.communicate()[0]
    exitCode = process.returncode

    if (exitCode == 0):
        return output
    else:
        raise ProcessException(command, exitCode, output)

So when i launch a process like Process.execute("mvn clean install"), my program waits until the process is finished, and only then i get the complete output of my program. This is annoying if i'm running a process that takes a while to finish.

Can I let my program write the process output line by line, by polling the process output before it finishes in a loop or something?

I found this article which might be related.

 Answers

90

You can use iter to process lines as soon as the command outputs them: lines = iter(fd.readline, ""). Here's a full example showing a typical use case (thanks to @jfs for helping out):

from __future__ import print_function # Only Python 2.x
import subprocess

def execute(cmd):
    popen = subprocess.Popen(cmd, stdout=subprocess.PIPE, universal_newlines=True)
    for stdout_line in iter(popen.stdout.readline, ""):
        yield stdout_line 
    popen.stdout.close()
    return_code = popen.wait()
    if return_code:
        raise subprocess.CalledProcessError(return_code, cmd)

# Example
for path in execute(["locate", "a"]):
    print(path, end="")
Tuesday, June 1, 2021
 
pop
answered 7 Months ago
pop
55

By using psutil:

import psutil, os

def kill_proc_tree(pid, including_parent=True):    
    parent = psutil.Process(pid)
    children = parent.children(recursive=True)
    for child in children:
        child.kill()
    gone, still_alive = psutil.wait_procs(children, timeout=5)
    if including_parent:
        parent.kill()
        parent.wait(5)

me = os.getpid()
kill_proc_tree(me)
Wednesday, June 2, 2021
 
BetaRide
answered 7 Months ago
47
  1. Make sure you can run powershell scripts (it is disabled by default). Likely you have already done this. http://technet.microsoft.com/en-us/library/ee176949.aspx

    Set-ExecutionPolicy RemoteSigned
    
  2. Run this python script on your powershell script helloworld.py:

    # -*- coding: iso-8859-1 -*-
    import subprocess, sys
    
    p = subprocess.Popen(["powershell.exe", 
                  "C:\Users\USER\Desktop\helloworld.ps1"], 
                  stdout=sys.stdout)
    p.communicate()
    

This code is based on python3.4 (or any 3.x series interpreter), though it should work on python2.x series as well.

C:UsersMacEwinDesktop>python helloworld.py
Hello World
Thursday, June 10, 2021
 
skrilled
answered 6 Months ago
17

I suggest that you use subprocess.getoutput() as it does exactly what you want—run a command in a shell and get its string output (as opposed to byte string output). Then you can split on whitespace and grab the first element from the returned list of strings.

Try this:

import subprocess
stdoutdata = subprocess.getoutput("wc --lines /var/log/syslog")
print("stdoutdata: " + stdoutdata.split()[0])
Monday, August 9, 2021
 
Abdel
answered 4 Months ago
98

This works both from a script and from the interactive interpreter, but not from IDLE:

subprocess.Popen(whatever, stdin=sys.stdout, stdout=sys.stdin)

You can't use the objects which IDLE assigns to sys.stdin and sys.stdout as arguments to subprocess.Popen. These objects (the interfaces to the IDLE shell window) are file-like, but they're not real file handles with fileno attributes, and Unix-like operating systems require a fileno to be specified as the stdin or stdout for a subprocess. I cannot speak for Windows, but I imagine it has similar requirements.

Tuesday, November 9, 2021
 
bshacklett
answered 4 Weeks ago
Only authorized users can answer the question. Please sign in first, or register a free account.
Not the answer you're looking for? Browse other questions tagged :  
Share