How to access the output of a program via pipe in python - python

I'm trying to pipe the output of a python script using os.popen() . Here my python script :
sample.py
while(True):
print("hello")
python version : 3.6.7
os : ubuntu 18.04
My script to do the process :
import os
import types
def sample_function():
pipe = os.popen('python3 /home/gomathi/sample.py')
while(True):
a = pipe.readline()
yield a
s=sample_function()
for i in s:
print(i)
It works well for the above code.Now the problem is , i have changed the sample.py as follows :
sample.py
print("hello")
It just print blank for the entire screen and continues printing blank characters . What went wrong with my code ? What changes to be made in my code to work for the above sample.py ?

Your new sample.py ends, but you keep reading from the pipe. So you're getting empty strings.

Use the subprocess module, with the same function Popen and redirect the output and the error to the print function of your main .py file.
from subprocess import Popen, PIPE
command = ['python3', '/home/gomathi/sample.py']
process = Popen(command, shell=False, stdout=PIPE, stdin=PIPE)
while True:
line = process.stdout.readline() #variable_name_changed
print(line)

Related

How to capture bash command output using python script

How to capture bash command output using python script.
For eg:
running below in linux :
[root#xxxxxx oracle]# echo sumit
sumit
[root#xxxxxx oracle]#
How can i re print only the above output using python script ? like running python test.py shoud give 'sumit' as output. i tried below:
test.py :
import sys
sys.stdout.flush()
out = sys.stdin.readline()
print(out)
Above prints only the input i type but not the already displayed output
With subprocess, you can run commands and check their return code, stdout and stderr outputs. Would that help?
For example:
import subprocess as proc
byte_output = proc.check_output(["ls", "-1", "."])
str_output = str(byte_output, "utf-8")
print(str_output)
# prints my local folders dev\ngit

Run cmd file using python

I have a cmd file "file.cmd" containing 100s of lines of command.
Example
pandoc --extract-media -f docx -t gfm "sample1.docx" -o "sample1.md"
pandoc --extract-media -f docx -t gfm "sample2.docx" -o "sample2.md"
pandoc --extract-media -f docx -t gfm "sample3.docx" -o "sample3.md"
I am trying to run these commands using a script so that I don't have to go to a file and click on it.
This is my code, and it results in no output:
file1 = open('example.cmd', 'r')
Lines = file1.readlines()
# print(Lines)
for i in Lines:
print(i)
os.system(i)
You don't need to read the cmd file line by line. you can simply try the following:
import os
os.system('myfile.cmd')
or using the subprocess module:
import subprocess
p = subprocess.Popen(['myfile.cmd'], shell = True, close_fds = True)
stdout, stderr = proc.communicate()
Example:
myfile.cmd:
#ECHO OFF
ECHO Grettings From Python!
PAUSE
script.py:
import os
os.system('myfile.cmd')
The cmd will open with:
Greetings From Python!
Press any key to continue ...
You can debug the issue by knowing the return exit code by:
import os
return_code=os.system('myfile.cmd')
assert return_code == 0 #asserts that the return code is 0 indicating success!
Note: os.system works by calling system() in C can only take up to 65533 arguments after a command (so it is a 16 bit issue). Giving one more argument will result in the return code 32512 (which implies the exit code 127).
The subprocess module provides more powerful facilities for spawning new processes and retrieving their results; using that module is preferable to using this function (os.system('command')).
since it is a command file (cmd), and only the shell can run it, then shell argument must set to be true. since you are setting the shell argument to true, the command needs to be string form and not a list.
use the Popen method for spawn a new process and the communicte for waiting on that process (you can time it out as well). if you whish to communicate with the child process, provide the PIPES (see mu example, but you dont have to!)
the code below for python 3.3 and beyond
import subprocess
try:
proc=subprocess.Popen('myfile.cmd', shell=True, stderr=subprocess.PIPE, stdout=subprocess.PIPE)
outs, errs = proc.communicate(timeout=15) #timing out the execution, just if you want, you dont have to!
except TimeoutExpired:
proc.kill()
outs, errs = proc.communicate()
for older python versions
proc = subprocess.Popen('myfile.cmd', shell=True)
t=10
while proc.poll() is None and t >= 0:
print('Still waiting')
time.sleep(1)
t -= 1
proc.kill()
In both cases (python versions) if you dont need the timeout feature and you dont need to interact with the child process, then just, use:
proc = subprocess.Popen('myfile.cmd', shell=True)
proc.communicate()

Communication of a python parent process and a python subprocess

I have only recently started working with the subprocess-module, so i am sure, this is a rookie-question:
I am trying to start a python-subprocess from a python 3.5.2. parent script and retrieve information from it:
import subprocess
process = subprocess.Popen(
'C:\\IDLEX (Python GUI).exe',
shell = True,
stdout = subprocess.PIPE,
)
while True:
lines = process.stdout.readlines()
for line in lines:
print (line)
What command do i have to give in the child-process to generate an output in the parent process?
I already tried print('something') and sys.stdout.write('something else') (coupled with sys.stdout.flush()) but nothing seems to work.
The subprocess is running and its output is already directed to the parent process. There is no output generated because of 'C:\\IDLEX (Python GUI).exe' does not flush anything to stdout.
Your script is working:
process = subprocess.Popen(
'echo Hello World', # or change to any other executable or script to test
shell = True,
stdout = subprocess.PIPE,
)
Output:
Hello World
You may try to run C:\\IDLEX (Python GUI).exe directly in the cmd to check.

Receive return data from subprocess in python

I'm spawning a process from a script using subprocess. My subprocess takes a JSON input and performs some operations and should return some real time data to the main process. How can I do this from subprocess?
I'm trying something like this. But it is throwing an error.
Following is may main process "main.py"
p = subprocess.Popen(['python','handler.py'],
stdin=subprocess.PIPE,stdout=subprocess.PIPE)
p.communicate(JSONEncoder().encode(data))
while True:
out = process.stdout.read(1)
if out == '' and process.poll() != None:
break
if out != '':
sys.stdout.write(out)
sys.stdout.flush()
Below is my subprocess "handler.py"
if __name__ == '__main__' :
command = json.load(sys.stdin)
os.environ["PYTHONPATH"] = "../../"
if command["cmd"] == "archive" :
print "command recieved:",command["cmd"]
file_ids, count = archive(command["files"])
sys.stdout.write(JSONEncoder().encode(file_ids))
But it throws an error.
Traceback (most recent call last):
File "./core/main.py", line 46, in <module>
out = p.stdout.read(1)
ValueError: I/O operation on closed file
Am I doing something wrong here??
Popen.communicate() does not return until the process is dead and it returns all the output. You can't read subprocess' stdout after it. Look at the top of the .communicate() docs:
Interact with process: Send data to stdin. Read data from stdout and
stderr, until end-of-file is reached. Wait for process to terminate.emphasis is mine
If you want to send data and then read the output line by line as text while the child process is still running:
#!/usr/bin/env python3
import json
from subprocess import Popen, PIPE
with Popen(command, stdin=PIPE, stdout=PIPE, universal_newline=True) as process:
with process.stdin as pipe:
pipe.write(json.dumps(data))
for line in process.stdout:
print(line, end='')
process(line)
If you need code for older python versions or you have buffering issues, see Python: read streaming input from subprocess.communicate().
If all you want is to pass data to the child process and to print the output to terminal:
#!/usr/bin/env python3.5
import json
import subprocess
subprocess.run(command, input=json.dumps(data).encode())
If your actual child process is a Python script then consider importing it as a module and running the corresponding functions instead, see Call python script with input with in a python script using subprocess.
communicate reads all the output from a subprocess and closes it. If you want to be able to read from the process after writing, you have to use something other than communicate, such as p.stdin.write. Alternatively, just use the output of communicate; it should have what you want https://docs.python.org/3/library/subprocess.html#popen-objects.

getting subprocess result in variable

I am executing python script using subprocess.call() in pytho script. The script which gets executed using subproecss is a server process which send result back to calling client.
result = subprocess.call('python -m module/coref_resolution/src/coref/corenlp &', shell = True)
Is there any way to receive result from corenlp.py into result variable?
import shlex
cmd = shlex.split('your command')
output = subprocess.Popen( cmd, stdout = subprocess.PIPE).communicate()[0]

Categories

Resources