I want to run a python script file with this ping -t www.google.com command.
So far I did one with the ping www.google.com command which works, but I didn't suceed to do on with the ping -t looping indefinitely.
You can find below my ping.py script:
import subprocess
my_command="ping www.google.com"
my_process=subprocess.Popen(my_command, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
result, error = my_process.communicate()
result = result.strip()
error = error.strip()
print ("\nResult of ping command\n")
print("-" *22)
print(result.decode('utf-8'))
print(error.decode('utf-8'))
print("-" *22)
input("Press Enter to finish...")
I want the command box to stay open when finished. I am using Python 3.7.
If you want to keep the process open and communicate with it all the time, you can use my_process.stdout as input and e.g. iterate over it's lines. With "communicate" you wait until the process completes, which would be bad for an indefinitely running process :)
import subprocess
my_command=["ping", "www.google.com"]
my_process=subprocess.Popen(my_command, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
while True:
print( my_process.stdout.readline() )
EDIT
In this version we use re to only get the "time=xxms" part from the output:
import subprocess
import re
my_command=["ping", "-t", "www.google.com"]
my_process=subprocess.Popen(my_command, stdout=subprocess.PIPE,
stderr=subprocess.PIPE)
while True:
line = my_process.stdout.readline() #read a line - one ping in this case
line = line.decode("utf-8") #decode the byte literal to string
line = re.sub("(?s).*?(time=.*ms).*", "\\1", line) #find time=xxms in the string and use only that
print(line)
Related
I am new to Python and Linux. I have a process running in a terminal window that will go indefinitely. The only way to stop it would be for it to crash or for me to hit ctrl+C. This process outputs text to the terminal window that I wish to capture with Python, so I can do some additional processing of that text.
I know I need to do something with getting stdout, but no matter what I try, I can't seem to capture the stdout correctly. Here is what I have so far.
import subprocess
command = 'echo this is a test. Does it come out as a single line?'
def myrun(cmd):
p = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
stdout = []
while True:
line = p.stdout.read()
stdout.append(line)
if line == '' and p.poll() != None:
break
return ''.join(stdout)
result = myrun(command)
print('> ' + result),
This will work when my command is a simple "echo blah blah blah". I am guessing this is because the echo process terminates. If I try running the continuous command, the output is never captured. Is this possible to do?
read() will block on reading until reach EOF, use read(1024) or readline() instead:
read(size=-1)
Read and return up to size bytes. If the argument is omitted, None, or negative, data is read and returned until EOF is reached.
eg:
p = subprocess.Popen('yes', stdout=subprocess.PIPE)
while True:
line = p.stdout.readline()
print(line.strip())
see more on the python io doc.
Thank you for taking the time to read this post.
I'm trying to do live bandwidth monitoring in python using vnstat. Unfortunately, It is not printing the output that i want, and i cant seem to figure out why. This is my code below.
from subprocess import Popen, PIPE
import time
def run(command):
process = Popen(command, stdout=PIPE, bufsize=1, shell=True ,universal_newlines=True)
while True:
line = process.stdout.readline().rstrip()
print(line)
if __name__ == "__main__":
run("sudo vnstat -l -i wlan1")
When i run this code in the terminal , this is the output i get :
sudo python testingLog.py
Monitoring wlan1... (press CTRL-C to stop)
It does not show me the desired output when running "vnstat -l -i wlan1" in the terminal.
Desired Output :
Monitoring wlan1... (press CTRL-C to stop)
rx: 0 kbit/s 0 p/s tx: 0 kbit/s 0 p/s
What happens when i run vnstat -l -i wlan1 is that it will update it and be running live, so i suspect that my printing is wrong as it does not print the desired output but i cant seem to figure out why.
It's not that your printing is wrong, it's the fact that vnstat keeps updating the same line without issuing a new line so process.stdout.readline() hangs at one point, waiting for a new line that never comes.
If you just want to redirect vnstat STDOUT to Python's STDOUT you can just pipe it, i.e.:
import subprocess
import sys
import time
proc = subprocess.Popen(["vnstat", "-l", "-i", "wlan1"], stdout=sys.stdout)
while proc.poll() is None: # loop until the process ends (kill vnstat to see the effect)
time.sleep(1) # wait a second...
print("\nProcess finished.")
If you want to capture the output and deal with it yourself, however, you'll have to stream the STDOUT a character (or safe buffer) at the time to capture whatever vnstat publishes and then decide what to do with it. For example, to simulate the above piping but with you in the driver's seat you can do something like:
import subprocess
import sys
proc = subprocess.Popen(["vnstat", "-l", "-i", "wlan1"], stdout=subprocess.PIPE)
while True: # a STDOUT read loop
output = proc.stdout.read(1) # grab one character from vnstat's STDOUT
if output == "" and proc.poll() is not None: # process finished, exit the loop
break
sys.stdout.write(output) # write the output to Python's own STDOUT
sys.stdout.flush() # flush it...
# of course, you can collect the output instead of printing it to the screen...
print("\nProcess finished.")
I want to read output line by line
below is my bash code (meta.sh)
#!/bin/bash
echo "hello!"
read -p "Continue?(y/n)"
[ "$REPLY" == "y" ] || exit
echo "lol"
below is my subprocess code (test.py)
import subprocess
def create_subprocess(Command):
proc = subprocess.Popen(
Command,
shell=True,
stdout=subprocess.PIPE,
stderr=subprocess.STDOUT,
bufsize=1
)
return proc
Command = "/root/Desktop/meta.sh"
proc = create_subprocess(Command)
while True:
line = proc.stdout.readline()
if not line: break
print line.strip()
now when i run "python test.py"
it shows
hello!
now when I press y and press enter then it shows
Continue?(y/n)
lol
what ideally it should show is this
hello!
Continue?(y/n)
now when I press y and press enter then it should show
lol
As I mentioned in the comment, the problem is that python's readline is waiting until it gets either an end of line or end of file, neither of which are produced by the read -p command (note that you type onto the same line, because there is not a line ending on that one). That means your readline doesn't give you anything back until after lol is printed. You can get around this by reading one char at a time though, like so:
while True:
cur = proc.stdout.read(1)
if(not cur):
break
sys.stdout.write(cur)
sys.stdout.flush()
though you'll have to import sys as well
This will display each character from proc.stdout as soon as it's read and not wait for newlines.
Folks....I have a script running in a Python program via a subprocess Popen
command to create a pipe with the output from the script. It is working. However I thought I would have to use the .communicate() command to process records in the pipe from my program. I was not able to get that working, but did get it working with this code. What did I do wrong when I tried to use the .communicate command?
import subprocess
nul_f = open('/dev/null', 'w')
try:
tcpdmp = subprocess.Popen(['/usr/bin/sudo /usr/sbin/tcpdump -A -n -p -l - i eth0 -s0 -w - tcp dst port 80'],
stdout=subprocess.PIPE, shell=True,
stderr=nul_f,)
print 'My Records'
i=0
# end_of_pipe = tcpdmp.communicate()
while i<10:
i=i+1
line = tcpdmp.stdout.readline()
print '\t --', i, line
except KeyboardInterrupt:
print 'done'
tcpdmp.terminate()
tcpdmp.kill()
nul_f.close()
Thanks for any suggestions and critiques.....RDK
ps...Running Raspbian Linux on a Raspberry pi....
.communicate() waits for the child process to end. tcpdump does not end peacefully that is why your code has except KeyboardInterrupt (to handle Ctrl+C).
Unrelated: you could replace the while loop with this:
from itertools import islice
for line in enumerate(islice(iter(tcpdump.stdout.readline, b''), 10), start=1):
print '\t --', i, line, #NOTE: comma at the end to avoid double newlines
See also, Stop reading process output in Python without hang?
There are various topics available on this very topic, "How to write output to the text file".
But my issue is different because the output to the command in question is continous.
What I want to do is, write the Output of the command cgps -s to the file aaa.txt
here is the code,
import signal
import os
import subprocess
p = subprocess.Popen(["cgps", "-s", ">> aaa.txt"], stdout=subprocess.PIPE,shell=True, preexec_fn=os.setsid)
os.killpg(p.pid, signal.SIGTERM)
The code doesn't work at all and no file is created with the name aaa.txt
When I execute this command through terminal,
cgps -s > aaa.txt
Then I have to press CTRL+C to terminate the output from being written on the output file because the output is continuous.
Is there any way to just capture one output and write it to the file and terminate it using Python or using Command line ?
So you are trying to create a pipe. Try this:
import subprocess
p = subprocess.Popen(["cgps", "-s"], stdout=subprocess.PIPE)
with open("aaa.txt", "w") as f:
while True:
line = p.stdout.readline()
if not line:
break
if some_condition(): # <-- check whether you have enough output
p.terminate()
break
f.writeline(line)
p.wait()