IPython - Hide traceback when SystemExit is raised - ipython

I'm surprised no one asked this issue before, but somehow I couldn't find an answer.
When raising SystemExit in a simple my_script.py.
import sys
sys.exit(2)
No traceback is displayed when running python my_script.py, as explained in python doc:
SystemExit: When it is not handled, the Python interpreter exits; no stack traceback is printed.
However when running with ipython, a traceback is printed:
$ ipython my_script.py
---------------------------------------------------------------------------
SystemExit Traceback (most recent call last)
my_script.py in <module>
2 import sys
3
----> 4 sys.exit(2)
SystemExit: 2
This is an issue when using argparse as parser.parse_args() call sys.exit() if parsing fail. So user see an unhelpful SystemExit: 2 rather than the error message printed above the traceback.
A workaround is to use os._exit but this feels very hacky and might not properly cleanup.
Is there a ipython flag which would silence/hide the traceback when SystemExit is raised, like with standard python interpreter ?

Here's a sample session with xmode 'plain':
In [1]: import argparse
In [2]: parser=argparse.ArgumentParser()
In [3]: parser.add_argument('foo')
Out[3]: _StoreAction(option_strings=[], dest='foo', nargs=None, const=None, default=None, type=None, choices=None, help=None, metavar=None)
In [4]: import sys; sys.argv
Out[4]:
['/usr/local/bin/ipython3',
'--pylab',
'qt',
'--nosep',
'--term-title',
'--InteractiveShellApp.pylab_import_all=False',
'--TerminalInteractiveShell.xmode=Plain']
In [5]: parser.parse_args()
usage: ipython3 [-h] foo
ipython3: error: unrecognized arguments: --pylab --nosep --term-title --InteractiveShellApp.pylab_import_all=False --TerminalInteractiveShell.xmode=Plain
An exception has occurred, use %tb to see the full traceback.
SystemExit: 2
/usr/local/lib/python3.8/dist-packages/IPython/core/interactiveshell.py:3426: UserWarning: To exit: use 'exit', 'quit', or Ctrl-D.
warn("To exit: use 'exit', 'quit', or Ctrl-D.", stacklevel=1)
In [6]: parser.parse_args([])
usage: ipython3 [-h] foo
ipython3: error: the following arguments are required: foo
An exception has occurred, use %tb to see the full traceback.
SystemExit: 2
/usr/local/lib/python3.8/dist-packages/IPython/core/interactiveshell.py:3426: UserWarning: To exit: use 'exit', 'quit', or Ctrl-D.
warn("To exit: use 'exit', 'quit', or Ctrl-D.", stacklevel=1)
This shows the error message produced by the parser, followed by the capture and traceback. This allows me to continue interactively.
With plain interpreter, I get the message followed by an exit.
2310:~/mypy$ python3
Python 3.8.5 (default, Jan 27 2021, 15:41:15)
[GCC 9.3.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import argparse
>>> parser=argparse.ArgumentParser()
>>> parser.add_argument('foo');
_StoreAction(option_strings=[], dest='foo', nargs=None, const=None, default=None, type=None, choices=None, help=None, metavar=None)
>>> parser.parse_args()
usage: [-h] foo
: error: the following arguments are required: foo
2311:~/mypy$
For me the whole purpose of using ipython is to try multiple things, without it quitting on me. Otherwise I'd run the script without the interactive layer.

Related

Pylint and Subprocess.Run returning Exit Status 28

I'm trying to run pylint using subprocess but getting a vague message stating non-zero exit status 28. I can not find any reference to an exit status 28 for either Pylint or subprocess.
I can only assume this is a pylint/windows issue as running some other typical commands e.g. head, works just fine as does running pylint directly in the console.
Running python 3.5 on Windows 10.
Any ideas?
MWE
import subprocess
cmd = 'pylint test_script.py'
subprocComplete = subprocess.run(cmd, shell=True, check=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
print(subprocComplete.stdout.decode('utf-8'))
Output
python35 pylint_subprocess_test.py
Traceback (most recent call last):
File "pylint_subprocess_test.py", line 3, in <module>
subprocComplete = subprocess.run(cmd, shell=True, check=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
File "C:\Python35\lib\subprocess.py", line 708, in run
output=stdout, stderr=stderr)
subprocess.CalledProcessError: Command 'pylint test_script.py' returned non-zero exit status 28
If the subprocess returns nonzero (which pylint often will), then subprocComplete never gets assigned to. You can catch the error, and the error object holds the output you want.
import subprocess
cmd = 'pylint test_script.py'
try:
subprocComplete = subprocess.run(cmd, shell=True, check=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
print(subprocComplete.stdout.decode('utf-8'))
except subprocess.CalledProcessError as err:
print(err.output.decode('utf-8'))

How to solve unrecognized arguments error?

The problem is that I can not get through the first step of running the simplest command. When I write this code
import argparse
parser = argparse.ArgumentParser()
parser.parse_args()
an then i get this error
usage: main.py [-h]
main.py: error: unrecognized arguments: -f
C:\Users\Saeid\AppData\Roaming\jupyter\runtime\kernel-301e1312-128e-4c4d-9ae8-
035b05a69a59.json
An exception has occurred, use %tb to see the full traceback.
SystemExit: 2
C:\Program Files\Anaconda3\lib\site-
packages\IPython\core\interactiveshell.py:2889: UserWarning: To exit: use
'exit', 'quit', or Ctrl-D.
warn("To exit: use 'exit', 'quit', or Ctrl-D.", stacklevel=1)
The argparse module is used to parse command line arguments. Hence, it doesn't make much sense to do so in an IPython or Jupyter notebook. The error propably stems from the fact that the notebook was invoked with an -f option.
As funky-future pointed out, you should not be using an IPython notebook with argparse. To test how it works, let's assume a file named test.py with the following content:
import argparse
parser = argparse.ArgumentParser()
parser.add_argument("echo")
args = parser.parse_args()
print(args.echo)
Now in your terminal (cmd or PowerShell) you go to the directory with the test.py file and type:
python test.py 123
The output should be:
123
Source
To avoid that error message, you can do
import argparse
parser = argparse.ArgumentParser()
parser.parse_args([])

Unable to set IPython prompt

I'm running ipython with the following:
c:\python27\scripts\ipython
I'm trying to restore old Python prompt behaviour (">>>") for some reasons.
I've tried to search internet extensively for that purpose, to no avail.
Then I reached for IPython documentation, which turned out to be confusing and unhelpful.
According to http://ipython.readthedocs.io/en/stable/config/details.html
To set the new prompt, assign it to the prompts attribute of the IPython shell:
In [2]: ip = get_ipython()
...: ip.prompts = MyPrompt(ip)
/home/bob >>> # it works
I get the exception that get_ipython is undefined:
[TerminalIPythonApp] ERROR | Exception while loading config file C:\Users\xxx\.ipython\profile_default\ipython_config.py
Traceback (most recent call last):
File "c:\python27\lib\site-packages\traitlets\config\application.py", line 562, in _load_config_files
config = loader.load_config()
File "c:\python27\lib\site-packages\traitlets\config\loader.py", line 457, in load_config
self._read_file_as_dict()
File "c:\python27\lib\site-packages\traitlets\config\loader.py", line 489, in _read_file_as_dict
py3compat.execfile(conf_filename, namespace)
File "c:\python27\lib\site-packages\ipython_genutils\py3compat.py", line 278, in execfile
exec(compiler(scripttext, filename, 'exec'), glob, loc)
File "C:\Users\rgomulk\.ipython\profile_default\ipython_config.py", line 9, in <module>
ip = get_ipython()
NameError: name 'get_ipython' is not defined
Python 2.7.8 (default, Jun 30 2014, 16:03:49) [MSC v.1500 32 bit (Intel)]
Type "copyright", "credits" or "license" for more information.
IPython 5.1.0 -- An enhanced Interactive Python.
? -> Introduction and overview of IPython's features.
%quickref -> Quick reference.
help -> Python's own help system.
object? -> Details about 'object', use 'object??' for extra details.
(With the following complete code in my ipython_config.py:
from IPython.terminal.prompts import Prompts, Token
class MyPrompt(Prompts):
def in_prompt_tokens(self, cli=None):
return [(Token.Prompt, ' >>>')]
ip = get_ipython()
ip.prompts = MyPrompt(ip)
After next round of googling I've added the following line to the config:
from IPython import get_ipython
This time the result was different:
[TerminalIPythonApp] ERROR | Exception while loading config file C:\Users\xxx\.ipython\profile_default\ipython_config.py
Traceback (most recent call last):
File "c:\python27\lib\site-packages\traitlets\config\application.py", line 562, in _load_config_files
config = loader.load_config()
File "c:\python27\lib\site-packages\traitlets\config\loader.py", line 457, in load_config
self._read_file_as_dict()
File "c:\python27\lib\site-packages\traitlets\config\loader.py", line 489, in _read_file_as_dict
py3compat.execfile(conf_filename, namespace)
File "c:\python27\lib\site-packages\ipython_genutils\py3compat.py", line 278, in execfile
exec(compiler(scripttext, filename, 'exec'), glob, loc)
File "C:\Users\rgomulk\.ipython\profile_default\ipython_config.py", line 11, in <module>
ip.prompts = MyPrompt(ip)
AttributeError: 'NoneType' object has no attribute 'prompts'
So the question is twofold:
1. How can I actually set the prompt/restore old prompt behaviour?
2. Why doesn't the code from IPython documentation work? Is that a bug in implementation or documentation?
IPython version and other versions already given in IPython output.
Regards,
Robert
After extensive search (it was really tedious and others are confused as well, especially from distinguishing between startup and configuration scripts) I've found this page: Jupyter prompts
Which led to (working) solution:
from IPython.terminal.prompts import Prompts
from pygments.token import Token
class MyPrompt(Prompts):
def in_prompt_tokens(self, cli=None):
return [(Token.Prompt, '>>> ')]
c.TerminalInteractiveShell.prompts_class = MyPrompt
(Please notice the lack of what seems to be required by official documentation Official IPython docs:
The files typically start by getting the root config object:
c = get_config()
Regards,
Robert
Another possibility - less generic - is to use predefined Prompt class:
from IPython.terminal.prompts import ClassicPrompts
c = get_config()
c.TerminalInteractiveShell.prompts_class = ClassicPrompts

Getting started with SciPy and first example doesn't run

Environment is Ubuntu 12.x LTS 64 bit. I ran the install as follows :
sudo apt-get install python-numpy python-scipy python-matplotlib ipython ipython-notebook python-pandas python-sympy python-nose
Everything installed great, and I tried out the 'getting started' example only to come upon this error as if my env. is't set correctly..
See orig # http://www.scipy.org/getting-started.html
usernamep#ubuntudev:~$ ipython --pylab
Python 2.7.3 (default, Sep 26 2013, 20:03:06)
Type "copyright", "credits" or "license" for more information.
IPython 0.12.1 -- An enhanced Interactive Python.
? -> Introduction and overview of IPython's features.
%quickref -> Quick reference.
help -> Python's own help system.
object? -> Details about 'object', use 'object??' for extra details.
Welcome to pylab, a matplotlib-based Python environment [backend: TkAgg].
For more information, type 'help(pylab)'.
In [1]: from scipy import special, optimize
In [2]: f = lambda x: -special.jv(3,x)
In [3]: sol = optimize.minimize(f, 1.0)
---------------------------------------------------------------------------
AttributeError Traceback (most recent call last)
/home/user/<ipython-input-3-ea43eb308d3c> in <module>()
----> 1 sol = optimize.minimize(f, 1.0)
AttributeError: 'module' object has no attribute 'minimize'
In [4]:
Do I need to reform their example's import? Checking their docs now...
optimize.minimize was introduced in Scipy v.0.11 (see http://docs.scipy.org/doc/scipy/reference/generated/scipy.optimize.minimize.html ).
On Debian, that would mean that you need Jessie or better. On Ubuntu, you appear to need raring or better.
Almost certainly the scipy you installed using apt-get is simply too old to have minimize: (0.10, I'd guess). The code works for me:
>>> from scipy import special, optimize
>>> def f(x): return -special.jv(3,x)
>>> sol = optimize.minimize(f, 1.0)
>>> sol
status: 0
success: True
njev: 17
nfev: 51
hess_inv: array([[ 4.70024446]])
fun: -0.43439442684052476
x: array([ 4.20118891])
message: 'Optimization terminated successfully.'
jac: array([ -3.72529030e-09])
I think you'll be better off using pip to install the stack.
python-scipy package in the Ubuntu 12 is a bit old. I think it is ver 0.9.0. The optimize.minimize function was added to scipy ver 0.11.0.

Eclipse using multiple Python interpreters with execnet

I'm using the execnet package to allow communication between Python scripts interpreted by different Python interpreters.
The following code (test_execnet.py):
import execnet
for python_version in ('python', 'python3'):
try:
gw = execnet.makegateway("popen//python="+python_version)
ch = gw.remote_exec('channel.send(1/3)')
res = ch.receive()
print(python_version, ': ', res, sep ="")
except:
print('problems with ', python_version)
Runs perfectly in the command-line Terminal, showing the following output:
$ python3 test_execnet.py
python: 0
python3: 0.333333333333
However, if I try to run the same code from within the Eclipse IDE, I get the following error:
'import site' failed; use -v for traceback
Traceback (most recent call last):
File "<string>", line 1, in <module>
File "<string>", line 4, in <module>
File "<string>", line 2, in <module>
File "/Library/Frameworks/Python.framework/Versions/3.1/lib/python3.1/site-packages/execnet/gateway_base.py", line 8, in <module>
import sys, os, weakref
File "/Library/Frameworks/Python.framework/Versions/3.1/lib/python3.1/os.py", line 380, in <module>
from _abcoll import MutableMapping # Can't use collections (bootstrap)
File "/Library/Frameworks/Python.framework/Versions/3.1/lib/python3.1/_abcoll.py", line 54
class Hashable(metaclass=ABCMeta):
^
SyntaxError: invalid syntax
problems with python
problems with python3
NOTE:
Eclipse Version: 3.6.0
PyDev Interpreter configured for the project: python3
"Preferences/Interpreter - Python"'s Python Interpreters:
python (/usr/bin/python)
python3 (/Library/Frameworks/Python.Framework/Versions/3.1/Resources/Python.app/Contents/MacOS/Python
EDIT:
I write a code to show the os.environ like this:
for python_version in ('python', 'python3'):
try:
import os
for item in os.environ:
print(item, '= ', os.environ[item])
except:
print('problems with ', python_version)
I got the following outputs:
eclipse_output.txt
terminal_output.txt
A FileMerge comparison of the files can be found at eclipse_output.txt vs. terminal_output.pdf.
Any hints?
Thanks
seems like pydev does site-customizations and particularly modifies things for interactive/console usage (judging from a very quick skim of http://github.com/aptana/Pydev/blob/master/plugins/org.python.pydev/pysrc/pydev_sitecustomize/sitecustomize.py ). This is not useful or fitting for execnet-mediated processes.
You could try to "del os.environ['PYTHONPATH']" before you invoke execnet.makegateway, or, to be more careful, just delete the sitecustomize part of it.
hth,
holger
'import site' failed; use -v for traceback
I have seen that when python was unable to find its landmark. Which that indicates there is a PYTHONHOME problem.
Check out http://docs.python.org/using/cmdline.html#envvar-PYTHONHOME maybe eclipse is screwing your environment up.
Edit:
Looked at your env dumps, looks like eclipse is definitely messing with PYTHONPATH, which will cause your child python processes to not work correctly.
Basically what you have going on here is eclipse starts a python v2 instance with a PYTHONPATH pointing to the python v2 directories. Then you spawn a python v3 process which tries to load its landmark from the python v2 directories...
You need to find a way to have eclipse not mess with the PYTHONPATH. I am not sure what eclipse is trying to do by doing that, but it is certainly no friend when you want to spawn new python processes.