Exit to command line in Python - python

I have a script that I want to exit early under some condition:
if not "id" in dir():
print "id not set, cannot continue"
# exit here!
# otherwise continue with the rest of the script...
print "alright..."
[ more code ]
I run this script using execfile("foo.py") from the Python interactive prompt and I would like the script to exit going back to interactive interpreter. How do I do this? If I use sys.exit(), the Python interpreter exits completely.

In the interactive interpreter; catch SystemExit raised by sys.exit and ignore it:
try:
execfile("mymodule.py")
except SystemExit:
pass

Put your code block in a method and return from that method, like such:
def do_the_thing():
if not "id" in dir():
print "id not set, cannot continue"
return
# exit here!
# otherwise continue with the rest of the script...
print "alright..."
# [ more code ]
# Call the method
do_the_thing()
Also, unless there is a good reason to use execfile(), this method should probably be put in a module, where it can be called from another Python script by importing it:
import mymodule
mymodule.do_the_thing()

I'm a little obsessed with ipython for interactive work but check out the tutorial on shell embedding for a more robust solution than this one (which is your most direct route).

Instead of using execfile, you should make the script importable (name=='main protection, seperated into functions, etc.), and then call the functions from the interpreter.

Related

Why can't I call other functions/commands after running main() from within script?

#!/usr/bin/env python3
import click
#click.command()
#click.option('--desiredrange', '-r', default=1)
def main(desiredrange):
print(desiredrange)
print('abcd')
main()
print('!!!!')
Running the above code gives me the following in the terminal:
1
abcd
But I do not get
!!!!
This scenario is true for other variations of code that include ANYTHING after the main() function. The script exits after executing this function. This is also true for any function i.e. if I placed the print('!!!!') inside another function, then called that function after main(), the script exits after main(), ignoring the second function.
If I removed 'click', such that the code looks like:
#!/usr/bin/env python3
def main():
print(1)
print('abcd')
main()
print('!!!!')
I will get the following printed to terminal:
1
abcd
!!!!
I can execute other functions after main(), as well as other commands. I run this script from terminal using ./script.py (applied chmod +x script.py). I also get no errors from BOTH scenarios.
Why is this?
The function named main that you defined isn't actually the one called directly by the line main(). Instead, the two decorators are creating a new value that wraps the function. This callable (I don't think it's necessarily a function, but a callable instance of click.core.Command; I'm not digging into the code heavily to see exactly what happens.) calls raises SystemExit in some way, so that your script exits before the "new" main actually returns.
You can confirm this by explicitly catching SystemExit raised by main and ignoring it. This allows the rest of your script to execute.
try:
main()
except SystemExit:
pass
print('!!!!')
Remember that decorator syntax is just a shortcut for function application. With the syntax, you can rewrite your code as
import click
def main(desiredrange):
print(desiredrange)
print('abcd')
x = main
main = click.command(click.option('--desiredrange', '-r', default=1)(main))
y = main
assert x is not y
main()
print('!!!!')
Since the assertion passes, this confirms that the value bound to main is not your original function, but something else.
The click module runs your script in standalone_mode which invokes the command and then shuts down the Python interpreter, rather than returning.
You can call your main with standalone_mode=False and it'll return and then continuing executing your additional statements.
#!/usr/bin/env python3
import click
#click.command()
#click.option('--desiredrange', '-r', default=1)
def main(desiredrange):
print(desiredrange)
print('abcd')
main(standalone_mode=False)
print('!!!!')
> python source.py -r 2
2
abcd
!!!!
Also check the documentation for click.BaseCommand:
standalone_mode – the default behavior is to invoke the script in standalone mode. Click will then handle exceptions and convert them into error messages and the function will never return but shut down the interpreter. If this is set to False they will be propagated to the caller and the return value of this function is the return value of invoke().

Exit shell script from python

I Have a shell script which in turn runs a python script, I have to exit from the main shell script when an exception is caught in python. Can anyone suggest a way on how to achieve it.
In Python you can set the return value using sys.exit(). Typically when execution completed successfully you return 0, and if not then some non-zero number.
So something like this in your Python will work:
import sys
try:
....
except:
sys.exit(1)
And then, as others have said, you need to make sure your bash script catches the error by either checking the return value explicitly (using e.g. $?) or using set -e.

How to catch exception from a system() command in python

I have a system() command and I want to catch the exception it may generate. The code that I have is:
def test():
filename = "test.txt"
try:
cmd = "cp /Users/user1/Desktop/Test_Folder/"+filename+" /Users/user1/Desktop/"
output = system(cmd)
except:
print 'In the except'
traceback.print_exc()
sys.exit(1)
if __name__ == '__main__':
test()
When I execute the above code and say the file that I want to copy is not present then the error is not caught and the code does not enter the except section. How can I catch such errors generated by system() commands?
Note: The above system() command is just an example. There are multiple such system() commands and each of them vary from one another
The system() command doesn't throw an exception on failure; it will simply return the exit status code of the application. If you want an exception thrown on failure, use subprocess.check_call, instead. (And, in general, using the subprocess module is superior in that it gives you greater control over the invocation as well as the ability to redirect the subprocess's standard input/output).
Note, though, that if most of the operations you are doing are simple filesystem operations like copying files from one location to another, that there are Python functions that do the equivalent. For example, shutil provides the ability to copy files from one location to another. Where there are Python functions to do the task, it is generally better to use those rather than invoke a sub process to do it (especially since the Python-provided methods may be able to do it more efficiently without forking a process, and the Python versions will also be more robust to cross-platform considerations).

Adding breakpoint command lists in GDB controlled from Python script

I'm using Python to control GDB via batch commands. Here's how I'm calling GDB:
$ gdb --batch --command=cmd.gdb myprogram
The cmd.gdb listing just contains the line calling the Python script
source cmd.py
And the cmd.py script tries to create a breakpoint and attached command list
bp = gdb.Breakpoint("myFunc()") # break at function in myprogram
gdb.execute("commands " + str(bp.number))
# then what? I'd like to at least execute a "continue" on reaching breakpoint...
gdb.execute("run")
The problem is I'm at a loss as to how to attach any GDB commands to the breakpoint from the Python script. Is there a way to do this, or am I missing some much easier and more obvious facility for automatically executing breakpoint-specific commands?
def stop from GDB 7.7.1 can be used:
gdb.execute('file a.out', to_string=True)
class MyBreakpoint(gdb.Breakpoint):
def stop (self):
gdb.write('MyBreakpoint\n')
# Continue automatically.
return False
# Actually stop.
return True
MyBreakpoint('main')
gdb.execute('run')
Documented at: https://sourceware.org/gdb/onlinedocs/gdb/Breakpoints-In-Python.html#Breakpoints-In-Python
See also: How to script gdb (with python)? Example add breakpoints, run, what breakpoint did we hit?
I think this is probably a better way to do it rather than using GDB's "command list" facility.
bp1 = gdb.Breakpoint("myFunc()")
# Define handler routines
def stopHandler(stopEvent):
for b in stopEvent.breakpoints:
if b == bp1:
print "myFunc() breakpoint"
else:
print "Unknown breakpoint"
gdb.execute("continue")
# Register event handlers
gdb.events.stop.connect (stopHandler)
gdb.execute("run")
You could probably also subclass gdb.Breakpoint to add a "handle" routine instead of doing the equality check inside the loop.

Stop Windows from closing Python

This question may have been asked a couple of times but I cannot seem to find it.
Basically I am just learning Python and I am on Windows, this means I double click the .py file and open it. This works great until an error appears, at which point Python calls exit and the window closes.
One way, of course, to get around this is to use the cmd program in Windows and run the Python program from there, however, is there a way to fix it so that my application doesn't bail out and close as soon as it hits an error if I open it from Windows Explorer?
while(True):
try:
number = input('Enter a number: ')
if(is_int(number) is False):
print('Please actually enter a number')
if(number > 0):
answer = input('Oh Noes you really want that?')
if(answer == 'yes'):
sys.exit(0);
except KeyboardInterrupt:
sys.exit(0)
except Exception as e:
input('')
In order to keep your program intact, e.g. to not introduce unwanted catch-em-all exception handling (aka pokemon handling) there are at least three options:
Use any console terminal, e.g. built-in cmd or powershell or any third-party console apps out there.
Use any IDE: pycharm, IDLE (python windows installer by default sets it up) or whatever you have capable of running python code.
Use text editor plugins for running python code. At least notepad++ and sublime text are capable of doing so.
I would recommend starting with option 1 for starters, then slowly move to option 3 for small scripts and projects, and option two for larger ones.
I you put an input function at the bottom of your script then it will hang there until you hit enter or close the command prompt. If you call an exit function put it immediately before the exit function is called. Otherwise place it at the bottom of the script.
Also I assume you have defined is_int already in your script?
What would you think it should do?
Python is drawing the window you see, if python crashes, the windows is going away.
You can run it trough cmd, or within an IDE. (like IDLE, that has some problem though when it comes to GUI)
Otherwise, add something like this at the end of the file
try:
run()
except Exception as inst:
print type(inst), inst.args
#it prints the exception
print sys.exc_traceback.tb_lineno
#if you want the line number where the error occurred in the source code
raw_input()
inst is the exception instance, you can see the type and the list of arguments.
Then with the sys module you can also see the line where the error occurred in the code.
This way every error will be handled and displayed before closing
Is this the right way?
No. You should really be using ad IDE (like Eclipse with PyDev or PyCharm).
After #SeçkinSavaşçı's extremely useful comment at the start:
The most common way is to let it wait for an input, then ignore the input and terminate the script.
Which took me a second to understand I went in search of how to do this, so first I saw to stop the script and used:
while(True):
try:
# Application code here
except:
input('')
Which worked really well to catch all errors, which unlike in PHP (which I have become comfortable with unfortunately) are all exceptions.
So the next part was to to tell me what error had occured and how to fix it, I needed a backtrace. It just so happens that the Python docs gave me the answer right here: http://docs.python.org/2/library/traceback.html#traceback-examples in an easy to see example:
exc_type, exc_value, exc_traceback = sys.exc_info()
print(traceback.print_exception(exc_type, exc_value, exc_traceback, limit=2, file=sys.stdout));
Add that above the input('') and I had my perfect error handling showing me everything I needed.
Thanks all,
Try import time and time.sleep(). Also, I recommend you to use IDLE or Geany. I've been using them and they work out well.

Categories