Reputation: 3687
I already know there is several questions targeting this theme, but none of them solved my specific problem. Or at least I could not find it.
I need to execute some program in background, wait for output and manipulate it. But the background program must keep executing.
The info from the background program that I need is located, precisely, in the second line of its output. There is no problem if this program blocks my code until reach this line. But it is essential that it unlocks after that line so I can perform other tasks completely unrelated with the background program.
Still, I cannot figure out how to accomplish this. I've read a lot the documentation of subprocess
module, in particular, subprocess.Popen
.
Being pratical: why this code does not work with ['localtunnel', '8000']
argument? It outputs nothing...
I know I do not need root privileges to execute this.
EDIT after answers from jadkik94 and fest
Unfortunately, both answers do not work for me. Maybe I am doing something wrong...
First of all. A 'sanity check':
import subprocess, threading, time
can_break = False
def run():
args = ["ping", "google.com"]
popen = subprocess.Popen(args, shell=False, stdout=subprocess.PIPE)
while not can_break:
print popen.stdout.readline()
t = threading.Thread(target=run)
try:
t.start()
while True:
print 'Main thread...'
time.sleep(1)
except KeyboardInterrupt:
can_break = True
The code above works properly with output similar to this:
Main thread...
PING google.com (74.125.234.160) 56(84) bytes of data.
64 bytes from plusone.google.com (74.125.234.160): icmp_req=1 ttl=54 time=82.5 ms
Main thread...
64 bytes from plusone.google.com (74.125.234.160): icmp_req=2 ttl=54 time=82.7 ms
[...]
But when I use it with the args
I want (args = ['localtunnel', 8000]
), the only output is Main thread...
.
When I call localtunnel
in the main thread (blocking), it returns the desired output:
In [x]: popen = subprocess.Popen(['localtunnel', '8000'])
This localtunnel service is brought to you by Twilio.
Port 8000 is now publicly accessible from http://????.localtunnel.com ...
This approach is based on jadkik94's answer. But fest's answer does not work either.
Upvotes: 3
Views: 17317
Reputation: 7078
You can run it in a thread (so that it doesn't block your code from running), and get the output until you get the second line, then wait for it to terminate. This is an example that will read the output from the command dir /s
on Windows to get all the directory listing.
import subprocess, thread, time
def run():
global can_break
args = ["dir", "/s"]
shell = True
count = 0
popen = subprocess.Popen(args, shell=shell, stdout=subprocess.PIPE)
while True:
line = popen.stdout.readline()
if line == "": continue
count += 1
if count == 2:
do_something_with(line)
break
print "We got our line, we are waiting now"
popen.wait()
print "Done."
can_break = True
def do_something_with(line):
print '>>> This is it:', line
thread.start_new_thread(run, tuple())
can_break = False
while not can_break:
print 'Wait'
time.sleep(1)
print 'Okay!'
Output will look like:
Wait >>> This is it: Volume Serial Number is XXXX-XXXX We got our line, we are waiting now Wait Wait Wait . . . Done. Wait Okay!
Upvotes: 0
Reputation: 1635
To launch a program in a non blocking way but still being able to see the output of program, the program has to be launched in a separate thread or process. Ryan has posted a nice code sample here: Python Subprocess.Popen from a thread
Keep in mind that the last line print myclass.stdout
will print the output how it appears at that time. If program is just being launched, it might not have output anything at all, so your code should probably read from myclass.stdout
until it receives the line you need.
Upvotes: 1