Interactive Python through a network socket
Project description
Sock Python: lightweight interactive Python sessions over a link
This package provides a server to execute given snippets of Python code, and relay selected results back to the client. The server works like an interactive Python session, taking inputs from client connections. It listens either to a streaming UNIX socket or to a TCP/IP port. Also included in this library is the client software for either issuing snippets for the server to run, or control the server instance remotely.
For Jupyter fans: you can understand this package as like a lightweight Python kernel mechanism, providing both the kernel and its client, in a Python programmatic form as well as simple command-line interface.
CRITICAL SECURITY WARNING
While it is possible, one should be careful not to bind the server to an externally visible IP interface. This would grant unauthenticated execution access to the machine to the whole network -- a very easy infiltration path for somebody to take over control of the machine. To be very clear, do not do this:
# NOOOO! DO NOT DO THIS
python -m sock_python --serve 0.0.0.0:9887
# NOOOOOOO! DO NOT DO THIS EITHER
python -m sock_python --serve my.domain.name:9887
The preferred way to serve is through a UNIX socket:
# This is the safest.
python -m sock_python --serve local/path/to/socket.sock
Alternatively, one may bind to their loopback interface, although this grants access to all other users that may be using the machine:
# This is risky, do it only if you understand the consequences.
python -m sock_python --serve localhost:9887
# Equivalent command line:
python -m sock_python --serve :9887 # Empty is filled with localhost.
This latter form is most useful when using the server over a SSH tunnel.
Final repeat: do not run the server bound to an external IP interface.
Installation
pip install sock_python
This package has no dependency.
Usage
This is a client-server system that articulates an interactive Python session. The server runs the Python code sent over by the client, and relays back strings with which code invokes the get function.
Command line interface (CLI)
To run the server, the part of the system that will run a sequence of Python snippets:
python -m sock_python --serve session.sock
The server will start listening on UNIX socket named session.sock in the current directory. It will also store this preferred session address in local file .sock_python.json. To change this session file, use option -f:
python -m sock_python -sf my_session.json session.sock
The server runs snippets forever. One can terminate the server by hitting Ctrl+C.
The client runs using the same command line, except for the -s/--serve command line option. The code snippet to send the server is provided at the standard input of the client: the unaware may feel that the client is stuck as it does nothing as it starts up. Type the code snippet, then Ctrl+D to have the client send it to the server. The snippet can get back some information from the server by invoking the get() function. Once the server is finished running the snippet, everything that the client getted is printed to standard output. Here is a full example:
python -m sock_python session.sock
a = 5
get(f"{a * 3}")
b = 8
get(a + b)
<CTRL+D>
15 13
The client can take advantage of the session file to avoid typing in the server's address.
# Assuming the server wrote its coordinates in file my_session.json
python -m sock_python -f my_session.json < snippet.py
# Or even better, using the default session file
python -m sock_python
from textwrap import dedent
get(dedent("""\
asdf
qwer
zxcv
"""))
<CTRL+D>
asdf
qwer
zxcv
If the code snippet given by the client raises an exception, its traceback is relayed back and printed on the client's standard error stream. The client process then terminates with a non-zero exit code.
Python usage
Running the server:
from sock_python import server_set_up
# The session is captured in implicit process state, as well as the module namespace
# in which the Python snippets are run. This namespace is encapsulated in a dictionary.
env = {}
with server_set_up("local.sock") as (address, serve):
print(address) # Effective address being served on.
# The serve function will service snippets forever! (Ctrl+C interrupts)
serve(env)
A TCP/IP address in the form of a tuple (host, port) can be given instead of a UNIX socket path string. If such a TCP/IP address is provided with port number 0, the underlying operating system binds the server to an ephemeral port, and this final address is what is captured by the address variable above. Naturally, in most cases, as is the case above, address takes the exact same value as the argument to server_set_up.
The client (in another thread or process):
from sock_python import run_snippet
snippet = """\
get(1 << 20)
"""
output, exception = run_snippet("local.sock", snippet)
Once again, a TCP/IP tuple address can be used instead. output contains the concatenation of all the getted strings. If the snippet runs without any runaway exception, exception is the empty string; otherwise, it is a string rendering of the exception's traceback.
In addition to running code snippets, an alternative client interface can be used to control the server process remotely.
from sock_python import Action, control
response = control("local.sock", Action.STOP)
The possible actions one can perform through this control interface:
Action.STOP: terminates the server, which will then exit gracefully.responseis an empty dictionary.Action.RESTART: restarts the server process, which will re-bind to the same address, but restart from a fresh process space. This is useful to reset the session to its initial state.responseis an empty dictionary.Action.STATUS: returns some status information about the server, provided as theresponsedictionary.
Some gotchas
The server is a single-threaded process
Therefore, it runs one snippet at a time, and only when done then processes further connections. If your snippet falls into an endless loop, the server will need restarting by interruption or process termination through the operating system services.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file sock_python-0.1.1.tar.gz.
File metadata
- Download URL: sock_python-0.1.1.tar.gz
- Upload date:
- Size: 15.2 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/5.1.1 CPython/3.12.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
9243895bfd77247460ae0149534a54e6ca2ee03d854405f83e9a42ad2bc2e10d
|
|
| MD5 |
2f68af695f5b4654cf86e5313d9d5015
|
|
| BLAKE2b-256 |
124664b25c96fe47aa9dc7efce671c4f853196020cf1f9ec25bfa44e25b3108d
|
File details
Details for the file sock_python-0.1.1-py3-none-any.whl.
File metadata
- Download URL: sock_python-0.1.1-py3-none-any.whl
- Upload date:
- Size: 11.1 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/5.1.1 CPython/3.12.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
db7f402645882de16ea4a635f863d2894b0a02ec84086f584fa616cc82e3236e
|
|
| MD5 |
f4a1e2ed61d0193a1f6a896a20c2fb1b
|
|
| BLAKE2b-256 |
d9dc0824bd94d43c5f204b57aab71bd315048a64f9a1b0442c77a082a44be026
|