sys.argv is different when in interactive mode in Ipython - ipython

When I run a script with Ipython in interactive mode, the sys.argv argument list is different in the interactive part of the execution than in the script.
Is this a bug, or am I doing something wrong?
Thanks!
oskar#RR06:~$ cat test.py
import sys
print(sys.argv)
temp = sys.argv
oskar#RR06:~$ ipython -i test.py -- foo bar
Python 2.7.6 (default, Jun 22 2015, 17:58:13)
Type "copyright", "credits" or "license" for more information.
IPython 4.2.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.
['/home/oskar/test.py', 'foo', 'bar']
In [1]: temp
Out[1]: ['/home/oskar/test.py', 'foo', 'bar']
In [2]: sys.argv
Out[2]: ['/usr/local/bin/ipython', '-i', 'test.py', '--', 'foo', 'bar']

If I just invoke ipython, and look at sys.argv I get
In [3]: sys.argv
Out[3]: ['/usr/bin/ipython3']
Your Out[2] looks the same - the full list as provided by the shell and Python interpreter. Remember we are running a Python session with ipython import:
#!/usr/bin/env python3
# This script was automatically generated by setup.py
if __name__ == '__main__':
from IPython import start_ipython
start_ipython()
/usr/bin/ipython3 (END)
But look at ipython -h; in the first paragraph:
it executes the file and exits, passing the
remaining arguments to the script, just as if you had specified the same
command with python. You may need to specify -- before args to be passed
to the script, to prevent IPython from attempting to parse them.
So it's explicitly saying that
ipython -i test.py -- foo bar
becomes (in effect) - or is run as:
python test.py foo bar
The ipython code has a parser (as subclass argparse) that handles many different arguments. But ones it can't handle, or follow -- are set aside, and put in the sys.argv that your test.py sees.
But apparently that sys.argv is not what is given to the interactive session.
I think you'd get the same effect
$ipython
In[0]: %run test.py foo bar
...
%run saves the current sys.argv, and constructs a new one with sys.argv = [filename] + args. Then after running your test.py it restores the sys.argv.
This is not a bug, and you aren't doing anything wrong - except expecting the two sys.argv to be the same. It appears that in a plain Python shell, the two sys.argv are the same (without any of the options that the shell itself uses).

Related

Executing a python file from IPython

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.

Is there an IPython equivalent to Bash's semicolon?

I use IPython as my interactive shell and I almost always run two commands at the start - something like:
%run helper_functions.py
data = import_data('file_with_data')
I would like a notation to run these two at the same time (so I could recall them with an "up" arrow from history) akin to what echo 1 ; echo 2 does in Bash.
I am aware that I can start IPython running with a script as per How can I start IPython running a script?.
Semicolon is a valid statement separator in Python, the same as the newline, so you can use it with regular commands:
a=5; a=a+1; print "This is a: %s" % a
Anyway, as pointed out by tobias_k, this is not working with "run" which is a special IPython macro (see the IPython built-in magic commands) and changes the command line interpretation. Instead of %run helper_functions.py; data = import_data('file_with_data'), you could use something almost equivalent:
__builtin__.execfile('helper_functions.py') ; data = import_data('file_with_data')
You don't have the trace in IPython, but still your script is executed and the variables are in your interactive namespace.

How can I open an IPython notebook without the output?

I have an IPython notebook where I've accidentally dumped a huge output (15 MB) that crashed the notebook. Now when I open the notebook and attempt to delete the troublesome cell, the notebook crashes again—thus preventing me from fixing the problem and restoring the notebook to stability.
The best fix I can think of is manually pasting the input cells to a new notebook, but is there a way to just open the notebook without any outputs?
you can use cli to clear outputs
jupyter nbconvert --ClearOutputPreprocessor.enabled=True --inplace Notebook.ipynb
There is this nice snippet (that I use as a git commit hook) to strip the output of an ipython notebook:
#!/usr/bin/env python
def strip_output(nb):
for ws in nb.worksheets:
for cell in ws.cells:
if hasattr(cell, "outputs"):
cell.outputs = []
if hasattr(cell, "prompt_number"):
del cell["prompt_number"]
if __name__ == "__main__":
from sys import stdin, stdout
from IPython.nbformat.current import read, write
nb = read(stdin, "ipynb")
strip_output(nb)
write(nb, stdout, "ipynb")
stdout.write("\n")
You can easily make it a bit nicer to use, currently you'd have to call it as
strip_output.py < my_notebook.ipynb > my_notebook_stripped.ipynb
If you are running jupyter 4.x, you will get some API deprecation warnings when running filmor's script. Although the script still works, I update the script a bit to remove the warnings.
#!/usr/bin/env python
def strip_output(nb):
for cell in nb.cells:
if hasattr(cell, "outputs"):
cell.outputs = []
if hasattr(cell, "prompt_number"):
del cell["prompt_number"]
if __name__ == "__main__":
from sys import stdin, stdout
from nbformat import read, write
nb = read(stdin, 4)
strip_output(nb)
write(nb, stdout, 4)
stdout.write("\n")
As for later versions of jupyter, there is a Restart Kernel and Clear All Outputs... option that clears the outputs but also removed the variables.
Here is a further modification from #Edward Fung's answer that will output the cleaned notebook to a new file rather than rely on stin and stout
from nbformat import read, write
def strip_output(nb):
for cell in nb.cells:
if hasattr(cell, "outputs"):
cell.outputs = []
if hasattr(cell, "prompt_number"):
del cell["prompt_number"]
nb = read(open("my_notebook.ipynb"), 4)
strip_output(nb)
write(nb, open("my_notebook_cleaned.ipynb", "w"), 4)
Using the --ClearOutputPreprocessor, you can reduce the size of your notebook file due to the outputs.
jupyter nbconvert --ClearOutputPreprocessor.enabled=True --inplace sample.ipynb
Note that --clear-output is the broken command like below:
jupyter nbconvert --clear-output --inplace sample.ipynb
In my case, I tried to see the answer to this question, but I found out that it is a command that cannot remove output.
I am not able to post a commenet, so feel free to edit/move to #Shumaila Ahmed answer.
I had to use quotes on the file path, as:
jupyter nbconvert --ClearOutputPreprocessor.enabled=True --inplace 'Notebook.ipynb'
Works like charm on Ubuntu 21.04, thanks!

IPython | Unix commands not working in script but working in command line interpreter

Below lines when i put them in test.py and runs it, gives me error but runs fine when i run them from command line.
pyvar = 'Hello world'
!echo "A python variable: {pyvar}"
jitu#jitu-PC:~/ipython/python$ ipython test.py
File "/home/jitu/ipython/python/test.py", line 2
!echo "A python variable: {pyvar}"
^
SyntaxError: invalid syntax
Any idea why it is not working ?
.py file are python script, they are supposed to be pure python, IPython will not try to do some "magic" on it. You should rename your script to .ipy if you want to use the syntactic sugar IPython offers on top of pure python syntax.
Note that all IPython syntactic sugar can be transformed into pure python (cf %hist vs %hist -t) that will be valid python syntax, but still need to have access to an IPython instance.

How to run IPython script from the command line - syntax error with magic functions, %

I want to run IPython from the command line. However, I get a syntax error on the first line, importing pylab with the magic function %pylab is giving a syntax error on the %. The command I am using is simply ipython -i script.py.
Any ideas how to solve this?
You need to name your file script.ipy. When it ends in .ipy it can contain ipython syntax.
From ipython --help:
Usage
ipython [subcommand] [options] [files]
If invoked with no options, it executes all the files listed in sequence
and exits, use -i to enter interactive mode after running the files. Files
ending in .py will be treated as normal Python, but files ending in .ipy
can contain special IPython syntax (magic commands, shell expansions, etc.)