python wait using a timeout for an external program to finish - python

Before I run my python script I need to check if an external program is running and wait for it to finish.
I have a few pieces but am having some difficulty putting it all together into a cohesive script.
I can use the following to get the PID of a program and a while loop which will timeout in 10 seconds
from subprocess import check_output
import time
def get_pid(name):
return check_output(["pidof",name])
print "%s" % get_pid("java")
timeout = time.time() + 10
test = 0
while True:
if time.time() > timeout:
print "exception goes here"
break
test = test + 1
time.sleep(1)
If the program is not running get_pid would fail and I think I need to catch the exception in that case? This is where I am not certain where to go. Maybe there is a better way to approach this?
==============
Here is an update which seems to work correctly.
from subprocess import check_output, CalledProcessError
import time
def get_pid(name):
try:
process_status = check_output(["pidof",name])
except CalledProcessError as e:
process_status = None
return process_status
timeout = time.time() + 10
program = "java"
while get_pid(program) != None:
time.sleep(1)
print "1 second loop"
if time.time() > timeout:
raise ValueError ('Timeout exceeded')
print "%s is not running" % program

You can try catching this exception. Because when check_output returns non zero exception instance of CalledProcessError is raised which can be handled. Like this.
from subprocess import CalledProcessError
def get_pid(name):
try:
process_status = check_output(["pidof",name])
except CalledProcessError as e:
process_status = None # You can additionally get return code in the returncode attribute and any output in the output attribute.
return process_status
Hope it works!

Have you tried using the try and except block?
E.g.
try:
#some code
except (RuntimeError, TypeError, NameError):
#pass etc.
You can read the docs here Handling Exceptions

Exception handling can be at the place where the exception is thrown. So if check_output is throwing exception, you could handle below way,
def get_pid(name):
pid_ = None
try:
pid_ = check_output(["pidof",name])
except:
pass
return pid_
#logic to wait for pid_ to finish if found

Related

How to print the reason for program exit / program termination / exit errors?

I managed to catch the termination with:
atexit.register(exitHandler)
But how to print out what happened on that point? I want to see if the program aborts due to an error, due to Crtl-C or normal stopping...
It's not the complete solution - but you could wrap code in try except
try:
YOUR CODE HERE
except Exception as e:
print(e)
You should catch KeyboardInterrupt for Ctrl-C. E.g.:
import sys
try:
# your code
except KeyboardInterrupt:
sys.exit('Abort by user interrupt')
except Exception as exc:
sys.exit(f'Abort on error: {exc}')

Looping a Function In Python

I have a Function used against multiple devices listed in a LIST. It throws the error if it doesn't work against a particular devices and the script breaks.
def macGrabber(child,switch,cat = False):
try:
if cat is False:
child.expect('.#')
child.sendline('sh mac address-table | no-more')
else:
child.sendline('sh mac address-table dynamic | i Gi')
child.expect('.#', timeout=3000)
except pexpect.TIMEOUT:
print child.before,child.after
child.close()
raise
macs = child.before
child.close()
macs = macs.splitlines()
print('Connection to %s CLOSED' % switch)
return macs
Can we loop it ( retry multiple times ) before it goes to "Except' ? OR
Can we skip it and try for next device if it fails ?
You need to call macGrabber inside a try...except block and call continue if you would like to continue looping without the program crashing.
multiple_devices = [
(child1, switch1, cat1),
(child2, switch2, cat2),
...,
]
for device in multiple_devices:
try:
macGrabber(*device)
except pexpect.TIMEOUT as e:
print(f'{device} timed out')
print(e)
continue # <--- Keep going!
For the first question, yes, you can retry multiple times. Keep an error counter, wrap the whole try/except in a loop, and when you get an exception check the error counter and keep looping if it's less than (say) 5, otherwise raise the error as you're already doing.
error_count = 0
while True:
try:
if cat is False:
child.expect('.#')
child.sendline('sh mac address-table | no-more')
else:
child.sendline('sh mac address-table dynamic | i Gi')
child.expect('.#', timeout=3000)
break
except pexpect.TIMEOUT:
++error_count
if error_count < 5:
continue
print child.before,child.after
child.close()
raise
For the second question, yes, you can skip the device if it fails by just putting return None in the except handling. But you also would need to adjust the calling code to properly handle a None result.

Why my python code terminates even though I have proper exception handling?

I have the following python code:
try:
subprocess.check_output('service uwsgi stop;pkill -f uwsgi', shell = True)
except:
sys.exit(0)
it should return always 0 but when I run it, it prints 'Terminated' and then I receive a non-zero return code.
Right now, sys.exit(0) will only be called when an exception is raised. To ensure that it is called every time, add a finally statement:
try:
subprocess.check_output('service uwsgi stop;pkill -f uwsgi', shell = True)
except:
# Handle the exception
finally:
sys.exit(0)

Remove Traceback statement in a KeyboardInterrupt

I have a simple script:
i=1
while True:
try:
print i
except KeyboardInterrupt:
raise Exception("Ended by user.")
i = i+1
and when I interrupt it, it prints out:
How can I have it just print out the last line "Exception: Ended by user.", and not the "Traceback..." statement.
to emulate the exception but without the traceback, you could just print a message and exit with a non-zero code:
except KeyboardInterrupt:
print("Ended by user.")
sys.exit(1)

Hive UDF with Python - Print exception on shell

In the code below, Whenever exception is caught, I would like to exit from the program & print the exception on shell
#stream.py
import hashlib
import sys
import os
import importlib
for line in sys.stdin.readlines():
try:
inpFile = "temp.py"
execfile(inpFile)
line1 = line.strip('\n').split('\t')
print "\t".join(line1)
except:
#exception expected "temp.py:File Not Found", how do I exit the code & print the exception on console ?
sys.exit(1)
Here is the Transform query to call the UDF:
Create table newtable as Select TRANSFORM(id,name) USING
'python stream.py' as (id,name) from mytable;
ideas appreciated.
if you want to catch a specific type of exception (for examle an IOError) you can use
except IOError as e:
and access the error string with e.strerror
if you want to catch all exception you can use sys.exc_info()[0] to access the last error message
for example
try:
1/0
except:
print sys.exc_info()[0]
would print
<type 'exceptions.ZeroDivisionError'>
If you are expecting a specific exception then you should trap that, not everything, which is what you are doing. But there is nothing in your code to generate a "File Not Found" anyway!
EDIT: question code changed! We really do wish to trap "everything". I am using Exception, which traps "almost" everything, see https://docs.python.org/2/library/exceptions.html
This uses Python 2 syntax:
import sys
for line in sys.stdin.readlines():
try:
inpFile = "temp.py"
execfile(inpFile)
line1 = line.strip('\n').split('\t')
print "\t".join(line1)
except Exception as err:
print >> sys.stderr, err # print to stderr (python 2 syntax)
sys.exit(1)

Categories

Resources