Connecting to a remote IPython instance - python

I would like to run an IPython instance on one machine and connect to it (over LAN) from a different process (to run some python commands). I understand that it is possible with zmq : http://ipython.org/ipython-doc/dev/development/ipythonzmq.html .
However, I can not find documentation on how to do it and whether it is even possible yet.
Any help would be appreciated!
EDIT
I would like to be able to connect to IPython kernel instance and send it python commands. However, this should not be done via a graphic tool (qtconsole) , but I want to be able to connect to that kernel instance from within a different python script...
e.g.
external.py
somehow_connect_to_ipython_kernel_instance
instance.run_command("a=6")

If you want to run code in a kernel from another Python program, the easiest way is to connect a BlockingKernelManager. The best example of this right now is Paul Ivanov's vim-ipython client, or IPython's own terminal client.
The gist:
ipython kernels write JSON connection files, in IPYTHONDIR/profile_<name>/security/kernel-<id>.json, which contain information necessary for various clients to connect and execute code.
KernelManagers are the objects that are used to communicate with kernels (execute code, receive results, etc.).
*
A working example:
In a shell, do ipython kernel (or ipython qtconsole, if you want to share a kernel with an already running GUI):
$> ipython kernel
[IPKernelApp] To connect another client to this kernel, use:
[IPKernelApp] --existing kernel-6759.json
This wrote the 'kernel-6759.json' file
Then you can run this Python snippet to connect a KernelManager, and run some code:
from IPython.lib.kernel import find_connection_file
from IPython.zmq.blockingkernelmanager import BlockingKernelManager
# this is a helper method for turning a fraction of a connection-file name
# into a full path. If you already know the full path, you can just use that
cf = find_connection_file('6759')
km = BlockingKernelManager(connection_file=cf)
# load connection info and init communication
km.load_connection_file()
km.start_channels()
def run_cell(km, code):
# now we can run code. This is done on the shell channel
shell = km.shell_channel
print
print "running:"
print code
# execution is immediate and async, returning a UUID
msg_id = shell.execute(code)
# get_msg can block for a reply
reply = shell.get_msg()
status = reply['content']['status']
if status == 'ok':
print 'succeeded!'
elif status == 'error':
print 'failed!'
for line in reply['content']['traceback']:
print line
run_cell(km, 'a=5')
run_cell(km, 'b=0')
run_cell(km, 'c=a/b')
The output of a run:
running:
a=5
succeeded!
running:
b=0
succeeded!
running:
c=a/b
failed!
---------------------------------------------------------------------------
ZeroDivisionError Traceback (most recent call last)
/Users/minrk/<ipython-input-11-fb3f79bd285b> in <module>()
----> 1 c=a/b
ZeroDivisionError: integer division or modulo by zero
see the message spec for more information on how to interpret the reply. If relevant, stdout/err and display data will come over km.iopub_channel, and you can use the msg_id returned by shell.execute() to associate output with a given execution.
PS: I apologize for the quality of the documentation of these new features. We have a lot of writing to do.

If you just want to connect interactively, you can use SSH forwarding. I didn't find this documented anywhere on Stack Overflow yet, yet this question comes closest. This answer has been tested on Ipython 0.13. I got the information from this blog post.
Run ipython kernel on the remote machine:
user#remote:~$ ipython3 kernel
[IPKernelApp] To connect another client to this kernel, use:
[IPKernelApp] --existing kernel-25333.json
Look at the kernel-25333.json file:
user#remote:~$ cat ~/.ipython/profile_default/security/kernel-25333.json
{
"stdin_port": 54985,
"ip": "127.0.0.1",
"hb_port": 50266,
"key": "da9c7ae2-02aa-47d4-8e67-e6153eb15366",
"shell_port": 50378,
"iopub_port": 49981
}
Set up port-forwarding on the local machine:
user#local:~$ ssh user#remote -f -N -L 54985:127.0.0.1:54985
user#local:~$ ssh user#remote -f -N -L 50266:127.0.0.1:50266
user#local:~$ ssh user#remote -f -N -L 50378:127.0.0.1:50378
user#local:~$ ssh user#remote -f -N -L 49981:127.0.0.1:49981
Copy the kernel-25333.json file to the local machine:
user#local:~$ rsync -av user#remote:.ipython/profile_default/security/kernel-25333.json ~/.ipython/profile_default/security/kernel-25333.json
Run ipython on the local machine using the new kernel:
user#local:~$ ipython3 console --existing kernel-25333.json
Python 3.2.3 (default, Oct 19 2012, 19:53:16)
Type "copyright", "credits" or "license" for more information.
IPython 0.13.1.rc2 -- 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.
In [1]: import socket; print(socket.gethostname())
remote

Update to minrk's answer after the split to jupyter. With
jupyter_client (4.1.1)
the simplest code is rather something like:
import jupyter_client
cf=jupyter_client.find_connection_file('6759')
km=jupyter_client.BlockingKernelClient(connection_file=cf)
km.load_connection_file()
km.execute('a=5')
Note that:
jupyter_client.BlockingKernelClient is also aliased with jupyter_client.client.BlockingKernelClient.
the shell (km.shell_channel) does not have the method execute() & get_msg() anymore.
Currently it is quite difficult to find an updated documentation; nothing yet on http://jupyter-client.readthedocs.org/en/latest/ for BlockingKernelClient. Some code in https://github.com/jupyter/jupyter_kernel_test. Any link welcome.

The above answers are a bit old. The solution for the latest version of ipython is much simpler but is not documented well at one place. So I thought I would document it here.
Solution to connect from any OS to a ipython kernel running on Windows
If either the client or server is a linux or other operating system, just change the location of kernel-1234.json appropriately based on Where is kernel-1234.json located in Jupyter under Windows?
On your windows based kernel start, make sure ipykernel is installed using pip install ipykernel
Start the ipykernel using ipython kernel -f kernel-1234.json
Locate the kernel-1234.json file on your Windows machine. The file will probably have a different number, not 1234 and will most likely be located in 'C:\Users\me\AppData\Roaming\jupyter\runtime\kernel-1234.json': https://stackoverflow.com/a/48332006/4752883
Install Jupyter Console (or Jupyter Qtconsole/notebook) using pip install jupyter-console or pip install qtconsole https://jupyter-console.readthedocs.io/en/latest/
If you are on Windows do a ipconfig to find out the ip address of your Windows server. (On Linux do a ifconfig at the shell prompt). In the kernel-1234.json file change the ip address from 127.0.0.1 to the ip address of your server. If you are connecting from another Windows server, then copy the kernel-1234.json file to your local computer and note down the path.
Navigate to the folder containing the kernel-1234.json and start Jupyter Console using jupyter console --existing kernel-1234.json

If you're using Anaconda, in OS X the JSON file is stored at
/Users/[username]/Library/Jupyter/runtime/
In Windows:
c:\Users[username]\AppData\Roaming\jupyter\runtime\

Related

Vscode not interactive with python. Mac M1 chip

I am on a Mac with M1 chip and I have a problem with my VScode and python. It stays stuck on the ZSH shell even when I type the command to switch to bash (chsh -s /bin/bash). Lets say I run a simple code:
import cowsay
import sys
if len(sys.argv) == 2:
cowsay.cow("Hello, " + sys.argv[1])
I am supposed to be able to type my name in the shell after my python file name and it should print the cow saying Hello, Noah.
When I do so ((base) noahhaitas#Noahs-Mac-mini ~ % python3 itunes.py Noah Haitas), this is what I get as a message in my shell:
(base) noahhaitas#Noahs-Mac-mini ~ % python3 itunes.py Noah Haitas
/Library/Frameworks/Python.framework/Versions/3.10/bin/python3: can't open file '/Users/noahhaitas/itunes.py': [Errno 2] No such file or directory
I am trying to figure out how I can switch fully to bash and have the $ in front instead of seeing the % of ZSH.
What can be done as this is frustrating and I looked everywhere online and tried pretty much every solution.
Vscode is just an editor, and the system terminal is still applied.
Use the following command in the terminal to switch bash and restart the terminal:
chsh -s /bin/bash
At the same time, you can also set manually in the vscode terminal. Take Windows as an example:
Read the docs for more details about terminal settings.
By the way, there is an error when you run the file. It seems that the python file is not run in the correct directory.

Issues trying to install AirFlow locally

I'm new at airflow and I'm trying to install locally, following the instructions on the link below:
https://airflow.apache.org/docs/apache-airflow/stable/start/local.html
I'm running this code (as mentioned on the link):
# Airflow needs a home. `~/airflow` is the default, but you can put it
# somewhere else if you prefer (optional)
export AIRFLOW_HOME=~/airflow
# Install Airflow using the constraints file
AIRFLOW_VERSION=2.2.5
PYTHON_VERSION="$(python --version | cut -d " " -f 2 | cut -d "." -f 1-2)"
# For example: 3.6
CONSTRAINT_URL="https://raw.githubusercontent.com/apache/airflow/constraints-${AIRFLOW_VERSION}/constraints-${PYTHON_VERSION}.txt"
# For example: https://raw.githubusercontent.com/apache/airflow/constraints-2.2.5/constraints-3.6.txt
pip install "apache-airflow==${AIRFLOW_VERSION}" --constraint "${CONSTRAINT_URL}"
# The Standalone command will initialise the database, make a user,
# and start all components for you.
airflow standalone
# Visit localhost:8080 in the browser and use the admin account details
# shown on the terminal to login.
# Enable the example_bash_operator dag in the home page
and getting this error:
File "C:\Users\F43555~1\AppData\Local\Temp/ipykernel_12908/3415008398.py", line 3
export AIRFLOW_HOME=~/airflow
^
SyntaxError: invalid syntax
Someone knows how to deal with it?
I'm running on windows 10, vs code (jupyter notebook).
Tks!
Airflow is only supported on Linux and it looks like you're trying to run this on a windows machine.
If you want to install Airflow on Windows you'll need to use something like Windows Subsystem for Linux (WSL) or Docker. There are some examples around which show you how to do this on WSL (and loads using docker) - Here is one of them with WSL.

Backup Postgres from Python on Win10

I'm trying to backup Postgres from Python on Win10.
I'm working on Anaconda python 3.8, Win10 machine with Postgres12 local. On path environment variable I have postgres (lib and bin), no anaconda, and python 3.8 (no the anaconda one).
I'm able to correctly backup the database using on window's command shell:
pg_dump --dbname=postgresql://postgres:password#127.0.0.1:5432/test > C:\backup\dumpfile3.dump
but when I run it on anaconda:
os.system("pg_dump --dbname=postgresql://postgres:password#127.0.0.1:5432/test > C:\backup\dumpfile3.dump" )
I get as output 1 , witch is error code. It creates the file, but it's empty.
Using:
import subprocess
stk= 'pg_dump --dbname=postgresql://postgres:password#127.0.0.1:5432/test > C:\backup\dumpfile3.dump'
try:
subprocess.check_output(stk, shell=True, stderr=subprocess.STDOUT)
except subprocess.CalledProcessError as e:
raise RuntimeError("command '{}' return with error (code {}): {}".format(e.cmd, e.returncode, e.output))
I get :
RuntimeError: command 'pg_dump --dbname=postgresql://postgres:password#127.0.0.1:5432/test > C:\backup\dumpfile3.dump' return with error (code 1): b"'pg_dump' is not recognized as an internal or external command,\r\noperable program or batch file.\r\n"
If I use: subprocess.run or subprocess.call I doesn't produce error, but the created file it's empty.
It seems that neither os.system or subprocess on the anaconda interpreter, got access to the environment variables on the command shell. How is this possible? and how I can overcome it?. It is different user invoking the shell?
Thanks in advance.
The Computer was restarted, and it solves the issue... . There was no change in the paths, I believe that from the moment things (python ,postgres, ...) were installed, the machine hasn"t been restarted.
import os
os.system("pg_dump --dbname=postgresql://postgres:password#127.0.0.1:5432/test > C:\backup\dumpfile3.dump" )
worked!, and
import subprocess
subprocess.call(r"C:\some\path\backup.bat")
also worked!. Inside backup.bat is:
pg_dump pg_dump --dbname=postgresql://postgres:password#127.0.0.1:5432/test > C:\backup\dumpfile3.dump
I imagine that the issue was that the anaconda interpreter need a system restart to get access to the environment variables (where the postgres variable was), witch make very little sense as return with error (code 1): b"'pg_dump' is not recognized as an internal or external command,\r\noperable program or batch file.\r\n" seen like a console message.
If anyone have a better explanation, is welcome.

Luigi Pipelining : No module named pwd in Windows

I am trying to execute the tutorial given in https://marcobonzanini.com/2015/10/24/building-data-pipelines-with-python-and-luigi/.
I am able to run the program on its own using local scheduler, giving me:
Scheduled 2 tasks of which:
* 2 ran successfully:
- 1 PrintNumbers(n=1000)
- 1 SquaredNumbers(n=1000)
This progress looks :) because there were no failed tasks or missing external de
pendencies
===== Luigi Execution Summary =====
However, to try the visualization on the server, when I try to run luigid --background, it throws me an error saying I dont have pwd module.
I cannot find a pwd module using pip for windows.
File "c:\users\alex\appdata\local\continuum\anaconda3\lib\site-packages
\luigi\process.py", line 79, in daemonize
import daemon
File "c:\users\alex\appdata\local\continuum\anaconda3\lib\site-packages
\daemon\__init__.py", line 42, in <module>
from .daemon import DaemonContext
File "c:\users\alex\appdata\local\continuum\anaconda3\lib\site-packages
\daemon\daemon.py", line 25, in <module>
import pwd
ModuleNotFoundError: No module named 'pwd'
I am working in Anaconda Spyder with Python 3.6
I was able to fix this by installing python-daemon==2.1.2
If you already have python-daemon, try downgrading to version 2.1.2
Do this before install luigi.
Example:
pip install python-daemon==2.1.2
then
pip install luigi.
For some reason, if you dont use the --background parameter on windows it will start just fine
just write luigid in cmd
The base problem here is that luigid --background is trying to spawn a python-daemon which is a unix-specific thing.
See section titled "The luigid server" here: http://luigi.readthedocs.io/en/stable/central_scheduler.html
Specifically:
Note that this requires python-daemon. By default, the server starts on AF_INET and AF_INET6 port 8082 (which can be changed with the --port flag) and listens on all IPs. (To use an AF_UNIX socket use the --unix-socket flag)
This existing stack overflow answer provides more detail:
How to start daemon process from python on windows?
Options I see here are:
Log a request with Luigi on github to improve their windows support to spawn Luigid as a windows process for the --background switch
Run a virtual machine with a proper Unix OS in it on Windows and run your Luigi pipelines there.
Follow Steven G's suggestion and run luigid in a separate command prompt
To reproduce the root cause of this issue, open a python prompt in windows and type:
>>import daemon
Traceback (most recent call last): File "", line 1, in
File "C:\Anaconda3\lib\site-packages\daemon__init__.py",
line 42, in
from .daemon import DaemonContext File "C:\Anaconda3\lib\site-packages\daemon\daemon.py", line 25, in
import pwd ModuleNotFoundError: No module named 'pwd'

how to execute remote python to open a web on remote machine by using a command on a local machine

I've been searching on net for a long time but I still don't get the answer.
Let me give an examle to describe my question more clearly:
machine A(local) is now conneted with machine B(remote).ALL I WANT TO DO is to :
run a command on A(local),then stop and wait ,and do nothing,and then,a web page is opened on B(remote) automatically.
P.S this python program is stored on machine B.
Here's what I've achived by now:
This is my python program named test.py,and it is stored on B under /home/pi/Documents:
import webbrowser
webbrowser.open('http://www.google.com')
On A,I used command:
ssh <username of B>#<ip of B> python /home/pi/Documents/test.py
After running the above command on A,there is no errors on A but also no action on B.
if I change the command into creating a file on B or sudo reboot,then after running this command there will be a file on B created or B is shut down successfully.
if I change the python program into printing something,like:
print("hello from B")
the content is magically printed on A's terminal.
It seems this command does not work well if I want to open a web on B or print somthing on B.
Can anyone help me with this or is there any other way to accomplish it?
helpless..
Someone has any ideas please???
Thanks in advance!
Assuming B is a Linux or Unix-like system, you have a DISPLAY problem. The webbrowser module locates a browser on the machine, and tries to open it on current display. It works when you launch it localy, but a ssh session has by default no configured display, so any attempt to launch a XWindow (GUI) application will fail.
The rationale behind it is that the -X and -Y flags of the ssh command allow to pass the client display to the server and open the window on the local screen (in your example on A). So if the permissions of the X servers on A and B are compatible, you could try:
A$ ssh -Y <username of B>#<ip of B> # open an interactive shell on B
B$ echo $DISPLAY # control the DISPLAY env variable
-> localhost:10.0 # common value for ssh transported DISPLAY
B$ python /home/pi/Documents/test.py # open the window on A
To force the opening on B, you could set the DISPLAY to localhost:0.0 (primary XWindow)
A$ ssh ssh <username of B>#<ip of B> # open an interactive shell on B
B$ DISPLAY = localhost:0.0 # sets the DISPLAY env variable
B$ export DISPLAY
B$ python /home/pi/Documents/test.py # open the window on B
You might need to tweek authorization of the XWindow servers (or use the awful xhost +) on A and/or B to make the above examples work
Once you have been able to successfully open a window on the proper screen, you will just have to set the DISPLAY environment variable to the correct value in your Python script before opening the browser window.
One of the simplest solutions is to use redirect of stdin
$ ssh pi#B python <<EOF
> print "Hello World from B"
> EOF
Hello World from B
$
However, if the script is quite big, it is better to copy py file to server B and then call ssh with the file name as #Eliethesaiyan suggested.
$ scp X.py pi#B:/home/pi/
X.py 100% 26 0.0KB/s 00:00
$ ssh pi#B python X.py
Hello World from B
$
I've tested this using a VM running Ubuntu, which OS are you running on your remote system? Here's my launch_google.py:
import os
os.environ["DISPLAY"] = ":0"
import webbrowser
webbrowser.open("https://google.com")
Launch this using:
ssh <user>#<IP Address> "python launch_google.py&"
I included the ampersand otherwise the ssh session remains open. The python process doesn't need to keep running.
It is important to set the DISPLAY environment variable before importing the webbrowser module, otherwise the browsers won't be setup correctly. You can verify this running python via SSH:
>>> import os
>>> "DISPLAY" in os.environ
False
>>> import webbrowser
>>> len(webbrowser._browsers)
0
>>> webbrowser.open("https://google.com")
False
>>> os.environ["DISPLAY"] = ":0"
>>> reload(webbrowser)
<module 'webbrowser' from '/usr/lib/python2.7/webbrowser.pyc'>
>>> len(webbrowser._browsers)
3
>>> webbrowser.open("https://google.com")
True
>>>

Categories

Resources