Reputation: 83377
I sometimes paste a list of commands to be executed in the Python interpreter (Interactive Mode (mirror)). By default, if one command fails (i.e., raises an error), the Python interpreter indicates the command has failed, then executes the subsequent commands.
Is there any way to configure the Python interpreter (Interactive Mode) so that it stops executing a list of commands whenever one command fails?
Answering the comments:
Code example that I paste in the Python interpreter:
1/0
print('yo')
I don't want yo
to be printed, since 1/0
raises an error.
I paste the list of commands, from the clipboard, to the Python interpreter
Upvotes: 2
Views: 84
Reputation: 9978
Borrowing heavily from @alfasin's answer, you can extend the InteractiveConsole
class.
To keep the interactive session running, but ignore the rest of the pasted commands, you can discard the input for a short while (I've used 1 second) after an exception. This means that the rest of the pasted commands are ignored, while leaving you with the session still running.
from code import InteractiveConsole
import sys
import time
WAIT_TIME = 1
class Shell(InteractiveConsole):
def __init__(self):
self.stdout = sys.stdout
InteractiveConsole.__init__(self)
return
def runcode(self, code):
try:
exec(code, self.locals)
except SystemExit:
raise
except:
self.showtraceback()
t_end = time.time() + WAIT_TIME
while time.time() < t_end:
_ = self.raw_input() # Extra pasted commands are discarded
if __name__ == '__main__':
sh = Shell()
sh.interact()
Note that the extra commands are still printed to the terminal, but aren't actually run.
Upvotes: 1
Reputation: 53535
You can extend InteractiveConsole
and create your own shell which bails out on error. You can even run it from within interactive-mode :)
Here's a small example:
from code import InteractiveConsole
import sys
class Shell(InteractiveConsole):
def __init__(self):
self.stdout = sys.stdout
InteractiveConsole.__init__(self)
return
def runcode(self, code):
try:
exec code in self.locals
except:
self.showtraceback()
sys.exit(1) # <-- this is the secret sauce!
if __name__ == '__main__':
sh = Shell()
sh.interact()
OUTPUT
>>> sh = Shell()
>>> sh.interact()
Python 2.7.6 (default, Jan 26 2016, 22:37:40)
[GCC 4.2.1 Compatible Apple LLVM 7.0.2 (clang-700.1.81)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
(Shell)
>>> 1
1
>>> 1+1
2
>>> 1/0
Traceback (most recent call last):
File "<console>", line 1, in <module>
ZeroDivisionError: integer division or modulo by zero
alfasi:~/Desktop >
Upvotes: 2
Reputation: 402872
I'm not sure how to fix this on a standard Python REPL, but you can definitely achieve this with IPython.
In IPython, when you paste code, it is treated as a single code block, rather than a bunch of individual statements.
For example, open an IPython interactive session on your terminal and paste this:
x = [1]
y = [1 for _ in range(100)]] # <------ SyntaxError
z = x + y
This is what it looks like when pasted:
In [136]: x = [1]
...: y = [1 for _ in range(100)]]
...: z = x + y
Now hit enter:
File "<ipython-input-136-20c7b020310a>", line 2
y = [1 for _ in range(100)]]
^
SyntaxError: invalid syntax
In contrast, on the standard REPL interpreter:
>>> x = [1]
>>> y = [1 for _ in range(100)]]
File "<stdin>", line 1
y = [1 for _ in range(100)]]
^
SyntaxError: invalid syntax
>>> z = x + y
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError: name 'y' is not defined
Upvotes: 1