I want to run magic command % somefile.py inside a jupyter notebook. However, this program requires variables from the main script - jupyter-notebook

To clarify, somfile.py needs variables that are generated from main.ipynb. So, when I simply do %run somefile.py I get this error:
NameError: name 'viewer' is not defined
This viewer is defined in the main code above. However, now if I use %load somefile.py and THEN run it, it works fine. But, the whole point of me doing this is to not show the users of my script, the nitty gritty details. I am preparing this for some students.

The documentation of the magic command %run covers use of the -i option to "run the file in IPython’s namespace instead of an empty one." You want to add that flag to your %run command:
viewer = "something"
%run -i my_script.py
It applies to notebook kernel namespace as IPython was incorporated into the IPython notebook, which became the Jupyter notebook project later.

Related

How do I have my Jupyter notebook server run arbitrary Python code before running notebook code?

I'm trying to replicate the functionality of the code editor on a platform I was previously using called Odoo.sh. The platform would let me create a .ipynb notebook, but in the cells I could reference pre-set variables which required no boilerplate code inside of the notebook. Extremely convenient.
If you're familiar with Odoo, it was like having odoo-bin shell be implicitly run before executing any of the cells inside the notebook. It was wonderful to work with, but Odoo.sh is proprietary, so I'm trying to replicate the same functionality on my local machine.
A minimal example of what I'm going for here would be to have the following python code run before executing any of my .ipynb notebook file's cells.
example_value = False
def example_func():
global example_value
example_value = True
example_func()
So that inside of any notebook's cells I could simply run something like example_value and get an output of True.
In the case of Odoo.sh it almost seemed like there was a special custom kernel set up that was nothing more than a regular Python 3 kernel with some initialization code. This may be exactly what was going on, but I don't know enough about how Jupyter works to know for myself. How do I replicate this functionality?
I figured it out! You need to create a custom kernel, but for this use case you can just reuse the default IPython kernel and just pass some variables into the user namespace.
First, create a Python file for your kernel. Let's use test_kernel.py. Here are the contents:
from ipykernel.ipkernel import IPythonKernel
from ipykernel.kernelapp import IPKernelApp
if __name__ == "__main__":
example_value = False
def example_func():
global example_value
example_value = True
example_func()
IPKernelApp.launch_instance(
kernel_class=IPythonKernel,
user_ns={"example_value": example_value})
See how the arbitrary code from the question is run before launching the kernel instance. Using the user_ns argument, we can pass arbitrary data to the user environment.
To get our kernel up and running we need to make a test directory and then a test/kernel.json file. It will have these contents:
{
"argv": ["python", "-m", "test_kernel", "-f", "{connection_file}"],
"display_name": "Test"
}
Let's install that bad boy. Run jupyter kernelspec install --user test. In that command, test is the name of the directory we created. The --user argument makes Jupyter install the kernel only for the current user. You don't have to use it if you don't want to.
Now we should be good to go! Start things up with jupyter notebook and you will see your new kernel is available to use when using notebooks. And check it out, we can see the variable we passed into the namespace:
Last of all, be sure to note that in order for this to work your test_kernel.py file will need to be somewhere where Python can import it. I'm not an expert on this, but from a bit of Googling I took this to mean that the directory containing the file should either be the current working directory or be in your PYTHONPATH.

Send line to console in Notepad++

Is there a way to execute commands line-by-line written in NPP editor in a console.
I have already looked at the following plugins, but they seem to execute a line or chunk of code as a standalone script (i.e. not interactive):
NPPExec;
NPPConsole;
This question is similar to this one:
Run selected line in notepad++ console
but in their case the code is being saved, executed, and stopped. But I would like an interactive console, i.e. it would bring up an instance of shell (or any other console), and I can send line-by-line code from NPP editor.
It sounds like you are looking for behaviour similar to IPython and the Jupyter Notebook or maybe just a regular debugger. I don't know of any plugin that can do that in Notepad++.
If interactive behaviour after initial execution will do (e.g. for inspection of variables), you can achieve that using the interactive flag -i in NppExec like this:
cd $(CURRENT_DIRECTORY)
python -u -i $(FILE_NAME)

Run python script using existing ipython kernel without console

I can run a python script from a bash shell like so:
>> python script.py
I can also start an iPython kernel and connect multiple iPython consoles to the same kernel like so:
>> ipython kernel
...
To connect another client to this kernel, use:
--existing kernel-8987.json
then, for as many consoles as I would like, I execute
>> jupyter console --existing kernel-8987.json
However, what I would like to do is start a kernel, but then run scripts without opening a console. I'd like to do something like this:
>> ipython --existing kernel-8987.json script.py
Is this possible to do this somehow?
Extending on the other answer and use the %run magic command1, it's possible to do this (which works for multiple-line scripts):
$ jupyter console --simple-prompt --existing kernel-8987.json <<< '%run script.py'
or (on Windows where <<< doesn't work)
> echo %run script.py | jupyter console --simple-prompt --existing kernel-8987.json
Unfortunately, this method still prints some redundant prompt (In[1]:) on the console.
Alternatively, using Python API: (create a script to execute this Python code) (on my machine, this method is much faster)
from jupyter_client.manager import KernelManager
manager=KernelManager(connection_file="full path to connection file.json")
manager.load_connection_file()
manager.client().execute("commands to execute")
The commands to execute might span multiple lines, or have the form %run file.py.
There's also silent=True, store_history=False as parameters to execute().
The full path to the connection file can be found as
Path(jupyter_core.paths.jupyter_runtime_dir()) / "kernel-8987.json", or
jupyter_client.connect.find_connection_file("kernel-8987.json") (find file with specific name), or
jupyter_client.connect.find_connection_file() (find the latest file)
See also jupyter-client documentation.
Disclaimer: Some of the code are taken from jupyter-vim plugin, and manager.load_connection_file and connect.find_connection_file appears to be undocumented.
1: As mentioned in the documentation, the file is executed in a new namespace unless you use -i.
It seems that jupyter has this functionality already built in.
$ jupyter run --existing kernel-8987.json script.py
I don't know if this was a feature addition since the OP, or if I was really stupid and didn't RTFM.
$ jupyter run --help
Run Jupyter kernel code.
Options
=======
...
--existing=<CUnicode>
Connect to an already running kernel
Default: ''
Equivalent to: [--JupyterConsoleApp.existing]
The other answers will run the code in the existing kernel, but still open a console in the process. The run subcommand does exactly what I requested: runs the code without opening an interactive console.
% jupyter console --version
6.2.0
I can exec one-liners from a file like this:
% jupyter console --simple-prompt --existing kernel-8987.json < script.py

Running a python .py file on Jetbrain Pycharm

I write my .py files using Pycharm JetBrains editors. When I run my codes, the output is shown in a console entitled "Run", without any prompt. Therefore, I dont have access to the variables of my code output. How can I force the pycharm to show the output of my codes in ipython console?
You can edit the Run Configuration and check the box "Show command line afterwards". This will run your script, but leave you in an interactive prompt. Everything from your script will have been imported and available.
As a note, if you install the IPython package (Preferences -> Project -> Project Interpreter, click + to add packages) then you can get a nicer console interpreter.
Finally, a different way to accomplish what you are looking for: run under Debug rather than Run. You can set a breakpoint and then use the debugger's Console right at the line you might be interested in.

Save ipython notebook as script programmatically

The excellent ipython notebook has a handy --script command line flag that automatically saves a copy of the notebook as a .py script file (removing any header and markdown cells). Is there a way to switch this feature on from inside the notebook itself after the notebook is opened? Apparently, this option is not accessible to the %config magic.
Is there a way to have a cell that does this conversion? Is there any command-line tool I could use to do the conversion, and just have that in a shell command run from the notebook? (It seems that nbconvert does not output to .py.)
The reason I ask is that I have a git repository of notebooks, and I need to make sure the .py files are kept up to date when users change the notebooks themselves because the .py files are used to create c++ code from the contents of the notebooks. But I can't rely on users to set the --script flag because they'll always forget. (And I include myself in that group of users.)
Better yet (at least for my purposes): ipython respects local copies of the ipython_notebook_config.py file. So I can just add
c = get_config()
c.NotebookManager.save_script = True
to such a file in my notebook directory. Apparently, ipython first reads ~/.ipython/profile_default/ipython_notebook_config.py, and then reads the local copy of that file. So it's safe to use without worrying about demolishing the user settings.
This was not at all clear to me from the documentation, but I just tried it and it worked.
Oh. My mistake. nbconvert can handle conversions to script. So I can do something like this:
!ipython nbconvert --to python MyNB.ipynb
Of course, this line will get saved to the script, which means the script will try to re-save the notebook to itself every time it's executed. That's a bit circular, and I can imagine it could cause problems with some of my more outlandish hacks. Instead, we can ensure that it's only run from ipython by wrapping it as follows:
try :
if(__IPYTHON__) :
!ipython nbconvert --to python MyNB.ipynb
except NameError :
pass
Note that the conversion process will automatically convert the ! syntax to something that is acceptable to plain python. This is apparently not the case with the --script conversion. So the extra-safe way to do this is
try :
if(__IPYTHON__) :
get_ipython().system(u'ipython nbconvert --to python MyNB.ipynb')
except NameError :
pass

Resources