This question has been asked before, but I have tried the solutions in related questions such as this to no avail.
I am having problems with Python's exit command, and I have ruled out a problem with my code as run by vanilla Python 3. The problem comes when I run it with iPython or in Spyder's iPython console.
When I use just a simple exit command, I get the error:
NameError: name 'exit' is not defined
I have already imported sys as suggested by the other link. The only thing that kind of works is to try sys.exit() in which case I get:
An exception has occurred, use %tb to see the full traceback.
SystemExit
C:\Users\sdewey\AppData\Local\Continuum\Anaconda3\lib\site-
packages\IPython\core\interactiveshell.py:2870: UserWarning: To exit: use
'exit', 'quit', or Ctrl-D.
warn("To exit: use 'exit', 'quit', or Ctrl-D.", stacklevel=1)
I only say that that "kind of works" because the error message is smaller so it's less annoying :).
Any ideas? Seems like an issue with iPython. I have encountered a different issue in Jupyter (which uses iPython) where quit was ignored entirely, which I posted about separately here
I've run into the same issue while running scripts containing exit() in Pycharm's IPython shell.
I learned here, that exit is intended for interactive shells, so behaviour will vary depending on how the shell implements it.
I could figure out a solution which would...
not kill the kernel on exit
not display a traceback
not force you to entrench code with try/excepts
work with or without IPython, without changes in code
Just import 'exit' from the code beneath into scripts you also intend to run with IPython and calling 'exit()' should work. You can use it in jupyter as well (instead of quit, which is just another name for exit), where it doesn't exit quite as silent as in the IPython shell, by letting you know that...
An exception has occurred, use %tb to see the full traceback.
IpyExit
"""
# ipython_exit.py
Allows exit() to work if script is invoked with IPython without
raising NameError Exception. Keeps kernel alive.
Use: import variable 'exit' in target script with 'from ipython_exit import exit'
"""
import sys
from io import StringIO
from IPython import get_ipython
class IpyExit(SystemExit):
"""Exit Exception for IPython.
Exception temporarily redirects stderr to buffer.
"""
def __init__(self):
# print("exiting") # optionally print some message to stdout, too
# ... or do other stuff before exit
sys.stderr = StringIO()
def __del__(self):
sys.stderr.close()
sys.stderr = sys.__stderr__ # restore from backup
def ipy_exit():
raise IpyExit
if get_ipython(): # ...run with IPython
exit = ipy_exit # rebind to custom exit
else:
exit = exit # just make exit importable
You can use system warnings to set those warning that you do not need as ignored. Example:
the function that you call from somewhere else:
def my_function:
statements
if (something happened that you want to exit):
import warnings
warnings.filterwarnings("ignore")
sys.exit('exiting...')
Related
I have a windows executable that I want to run over and over. The problem is that sometimes there's an error about 1 second in, but the program doesn't exit. So what I would like to do is to be able to grab the contents of stdout, recognize there is an error, and then kill the subprocess and start it over.
When I run this executable, stuff prints to the screen just fine. But when I wrap it in a subprocess from python then the stdout stuff doesn't show up until the program terminates.
I've tried basically everything posted here with no luck:
Constantly print Subprocess output while process is running
Here's my current code, I replaced the executable with a second python program just to remove any other weird variables:
parent_program.py:
import subprocess, os, sys
program = "python "+os.path.dirname(os.path.abspath(__file__)) + "/child_program.py"
with subprocess.Popen(program, shell=True, stdout=subprocess.PIPE, bufsize=1, universal_newlines=True) as p:
for line in p.stdout:
print(line, end='')
child_program.py:
from time import sleep
for i in range(0,10):
print(i)
sleep(1)
What I would expect is that I would see 1,2,3,4... printed one second at a time, as if I had just run python child_program.py, but instead I get nothing for 10 seconds and then get all the output at once.
I also thought about trying to run the program from the CMD prompt and piping the stdout to a file python child_program.py 2>&1 > output.txt and then having python read that file, but it's the same problem, the file doesn't get written until the program terminates.
Is there any way to fix this on windows?
If I select the following code and click "Run selected Code" in eclipse, it will give me an error.
class abc(object):
def __init__(self):
print 'base'
def run(self):
print 'run'
Error message:
class abc(object):
def __init__(self):
print 'base'
def run(self):
print 'run'
File "<ipython-input-22-8e1ec627fd90>", line 1
def run(self):
^
SyntaxError: unexpected EOF while parsing
run
However, if I remove the space between the two functions then it will run Ok(see below), is this a bug in pydev? Any way I can over come this issue?
class abc(object):
def __init__(self):
print 'base'
def run(self):
print 'run'
Versions:
Eclipse 4.4.2
LiClipse 2.0.0.201504092214
Subclipse (Required) 1.10.13
I think what you're seeing is the result of using the interactive console to run your code (i.e.: http://www.pydev.org/manual_adv_interactive_console.html).
The issue is that when you send the code to the console through that action, it won't do any edit to your code, and when the console sees a line with 0-width, it'll conclude that the Python block is finished.
So, there are some workarounds for that:
Don't right-trim your blocks (i.e.: leave spaces to the block indent instead of a 0-width line).
If you don't want to run just a section of your code, deselect all the code and execute the whole file with Ctrl+Alt+Enter.
Deselect the code, go to the first line and send the contents to the console line-by-line with F2 (F2 will send the current line and will move the cursor to the next line with contents and may even fix the indents, so, it should be easy to select the block you want to send to the console).
Don't use the interactive console and do a plain run with F9 (although in this case as it'll launch in a new non-interactive console, the symbols won't be available for inspection afterwards).
If you work using TDD (test driven development), then run the test code with Ctrl+F9 (see http://www.pydev.org/manual_adv_pyunit.html for details) -- again, in this mode it won't be using the interactive console.
I'm relatively new to NumPy/SciPy and IPython.
To execute a python script in the python interactive mode, we may use the following commands.
>>> import os
>>> os.system('executable.py')
Then the print outputs can be seen from the python prompt.
But the same idea doesn't work with IPython notebook.
In [64]:
import os
os.system('executable.py')
Out[64]:
0
In this case, I cannot see any print outputs. The notebook only tells weather execution was successful or not. Are there any ways to see the outputs when I use IPython notebook?
Use the magic function %run:
%run executable.py
This properly redirects stdout to the browser and you will see the output from the program in the notebook.
It gives you both, the typical features of running from command line plus Python tracebacks if there is exception.
Parameters after the filename are passed as command-line arguments to
the program (put in sys.argv). Then, control returns to IPython's
prompt.
This is similar to running at a system prompt python file args,
but with the advantage of giving you IPython's tracebacks, and of
loading all variables into your interactive namespace for further use
(unless -p is used, see below).
The option -t times your script. With -d it runs in the debugger pdb. More nice options to explore.
Below is the code written in a script say test_atexit.py
def exit_function():
print "I am in exit function"
import atexit
atexit.register(exit_function)
print "I am in main function"
When i run the function using python2.4 then exit_function is being called
$python2.4 test_atexit.py
I am in main function
I am in exit function
When i run the same using ipython then exit_function is not being called
$ ipython
In [1]: %run test_atexit.py
I am in main function
In [2]:
why exit_function is not called when running script using Ipython and how can i make ipython to call exit_function
atexit functions are called when the Python interpreter exits, not when your script finishes. When you %run something in IPython, the interpreter is still running until you quit IPython. When you do that, you should see the output from your exit_function().
Possibly what you want is a try/finally, which ensures that the finally code is run after the try block, even if an exception occurs:
try:
print("Doing things...")
raise Exception("Something went wrong!")
finally:
print("But this will still happen.")
If you really need to make atexit functions run, then you can call atexit._run_exitfuncs. However, this is undocumented, and it may do unexpected things, because anything can register atexit functions - IPython itself registers half a dozen, so you're likely to break things if you do it in IPython.
(Also, Python 2.4? For the sanity of developers everywhere, if it's possible to upgrade, do so ;-) )
I'm interested in implementing a behavior in IPython that would be like a combination of ! and !!. I'm trying to use an IPython terminal as an adjunct to my (Windows) shell. For a long running command (e.g., a build script) I would like to be able to watch the output as it streams by as ! does. I would also like to capture the output of the command into the output history as !! does, but this defers printing anything until all output is available.
Does anyone have any suggestions as to how to implement something like this? I'm guessing that a IPython.utils.io.Tee() object would be useful here, but I don't know enough about IPython to hook this up properly.
Here is a snippet of code I just tried in iPython notebook v2.3, which seems to do what was requested:
import sys
import IPython.utils.io
outputstream = IPython.utils.io.Tee("outputfile.log", "w", channel="stdout")
outputstream.write("Hello worlds!\n")
outputstream.close()
logstream=open("outputfile.log", "r")
sys.stdout.write("Read back from log file:\n")
sys.stdout.write(logstream.read())
The log file is created in the same directory as the iPython notebook file, and the output from running this cell is displayed thus:
Hello worlds!
Read back from log file:
Hello worlds!
I haven't tried this in the iPython terminal, but see no reason it wouldn't work as well there.
(Researched and answered as part of the Oxford participation in http://aaronswartzhackathon.org)