I am currently trying to get the process id of a process started with subprocess.check_call.
i.e.
from subprocess import check_output
# I want to retrieve the PID of this process:
try:
p = check_output(['some broken program'])
except:
if CalledProcessError: # but Popen does not throw me a CalledProcessError even if program crashes
print("triage some stuff")
print(p.pid) # this doesn't work unless its Popen
I have tried using Popen which works perfectly, however, it doesn't seem to be able to catch when a program is terminated i.e. CalledProcessError.
Can anyone advise, whether there is a way to get around either problem? Thanks!
You have to import CalledProcessError too. Code (with check_output): from subprocess import check_output, CalledProcessError
To detect a specific exception you have to use the following syntax:
try:
statement
except ExceptionName:
another_statement
In your situation:
try:
p = check_output(['some broken program'])
except CalledProcessError:
print("triage some stuff")
You cannot reference p inside the except block as p may be undefined.
Moreover, as stated in this post, subprocess.run() is recommended over subprocess.check_output()
Related
I want to run a subprocess to check if python-docx is installed similar to this, where the lines
verify_installation = subprocess.run(["pdftotext -v"], shell=True)
if verify_installation.returncode == 127:
checks if pdftotext is installed or not and if it is not installed (returncode ==127), then it raises an exception.
I want to have a similar implementation to check if python-docx is installed, however, while debugging in Colab, even after installing python-docx, the same returncode is returned.
What is the interpretation of (returncode ==127) and how do I raise an exception only when the library is not installed.
Also what exactly does subprocess.run(["pdftotext -v"], shell=True) achieve.
I can recommend for different approach for this, pass PIPEs to the stderr and stdout for the spawned process and check those pipes after child return.
import subprocess
outs=None
errs=None
try:
proc=subprocess.Popen(["pdftotext -v"], 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()
#parse the stderr and stdoutput of proc:
f_check_if_has_errors(errs, outs)
Also consider to use/look subprocess.check_call method below:
try:
proc = subprocess.check_call(["pdftotext -v"], shell=True)
proc.communicate()
except subprocess.CalledProcessError:
# There was an error - command exited with non-zero code
I found a solution, it doesn't use subprocess as I mentioned, but I am including the answer to make sure someone who faces a similar problem "To check if a module is installed and if not to catch the error" can try it.
try:
import docx
except ImportError as e:
raise Exception(
#do something
)
In case importing the module creates problems, I'm still looking for a solution that runs shell subprocesses without having to import the module.
I am running a python script from another python script and I am wondering how I can catch exceptions from the parent python script.
My parent python script calls another python script n amount of times. Eventually that called script will exit with a 'ValueError' exception. I'm wondering if there is a way for my parent python script to notice this and then stop executing.
Here is the base code as-is:
import os
os.system('python other_script.py')
I have tried things such as this to no avail:
import os
try:
os.system('python other_script.py')
except ValueError:
print("Caught ValueError!")
exit()
and
import os
try:
os.system('python other_script.py')
except:
print("Caught Generic Exception!")
exit()
The os.system() always returns an integer result code. And,
When it returns 0, the command ran successfully;
when it returns a nonzero value, that indicates an error.
For checking that you can simply add a condition,
import os
result = os.system('python other_script.py')
if 0 == result:
print(" Command executed successfully")
else:
print(" Command didn't executed successfully")
But, I recommend you to use subprocess module insted of os.system(). It is a bit complicated than os.system() but it is way more flexible than os.system().
With os.system() the output is sent to the terminal, but with subprocess, you can collect the output so you can search it for error messages or whatever. Or you can just discard the output.
The same program can be done using subprocess as well;
# Importing subprocess
import subprocess
# Your command
cmd = "python other_script.py"
# Starting process
process = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE.PIPE)
# Getting the output and errors of the program
stdout, stderr = process.communicate()
# Printing the errors
print(stderr)
Hope this helps :)
Is there a doc somewhere which indicates what the different return codes of python's subprocess check_output() command means? I'm seeing the returncode equal 3, and I have no idea what is setting that value and/or what it means.
Example code:
try:
output = subprocess.check_output(cmd,
stderr=subprocess.STDOUT)
except subprocess.CalledProcessError as e:
print e.returncode
This code is printing 3.
The Python subprocess.check_output() doesn't itself return a code, it returns the output of the command being run. The doco can be found here.
If you're seeing an error code in that string, it's almost certainly specific to whatever you're trying to run, not a result of subprocess itself.
If, however, you're capturing the CalledProcessError exception caused by a non-zero return code (which can be extracted from the returncode attribute), that's still specific to whatever you're running.
In both cases, the documentation you need to check is that of whatever tool subprocess is running.
I am able to catch it with subprocess.CalledProcessError, however I want to ensure that there it was RuntimeError. I am using "subprocess.check_call" method.
I tried something like this and it didn't work.
try:
subprocess.check_call(arguments, cwd=<my_cwd>)
except subprocess.CalledProcessError:
try:
raise
except RuntimeError:
print "Runtime Error....."
I think you can't do what you want. Look at the description of the check_call method.
Run command with arguments. Wait for command to complete. If
the exit code was zero then return, otherwise raise
CalledProcessError. The CalledProcessError object will have the
return code in the returncode attribute.
The arguments are the same as for the call function.
Example:
check_call(["ls", "-l"])
If you are calling a python script using subprocess.check_call you can't tell if a RuntimeError occurred since the only thing that matters is the return code of the script.
It is impossible to do what you're asking. They are separate processes. The parent can't catch any exceptions raised by the child. The CalledProcessError you're able to catch is raised by check_call in the parent itself, after examining the exit status of the child.
I am executing commands through subprocess.check_output() because i want the o/p of it to be stored in a buffer.
Now, while doing this if command gets failed or if there is any error then it is causing problem for my whole application.
What i want is, even if command fails it should just print and go on for next instruction.
Can anybody help me to solve it?
Below is the sample code.
from subprocess import check_output
buff=check_output(["command","argument"])
if buff=="condition":
print "Do Some Task "
One way to do this would be to use the Popen.communicate method on a Process instance.
from subprocess import Popen, PIPE
proc = Popen(["command", "argument"], stdout=PIPE, stderr=PIPE)
out, err = proc.communicate() # Blocks until finished
if proc.returncode != 0: # failed in some way
pass # handle however you want
# continue here