Skip to main content

Call Python functions across processes as easily as local function calls - Simple RPC and IPC for Python

Project description

remotefunc

Call Python functions across different processes as easily as local functions.

An ultra-simple, zero-configuration RPC (Remote Procedure Call) library that makes inter-process communication (IPC) in Python feel like magic. No complex setup, no message queues, no serialization headaches - just pure Python functions that work across process boundaries.

Quick Start

Server Process (daemon.py)

from remotefunc import shared
import time

# Your shared data
items = []

# Make any function callable from other processes
@shared
def push_new_item(item: dict) -> int:
    items.append(item)
    return len(items)

@shared
def get_items() -> list:
    return items

# more code that keeps this process running

Client Process (controller.py)

from daemon import push_new_item, get_items

# Call remote functions exactly like local functions!
new_id = push_new_item({'x': 10, 'y': 20})
print(f'New item pushed, id: {new_id}')  # Output: New item pushed, id: 1

all_items = get_items()
print(f'All items: {all_items}')  # Output: All items: [{'x': 10, 'y': 20}]

That's it! No server setup, no configuration files, no complicated API calls.

Installation

pip install remotefunc

Or install from source:

git clone https://github.com/mortasen/remotefunc.git
cd remotefunc
pip install -e .

What is this library perfect for?

  • ๐Ÿ”„ Sharing data between Python processes without files or databases
  • ๐ŸŽฎ Building daemon/controller architectures with minimal boilerplate
  • ๐Ÿš€ Distributed Python applications that need simple process communication
  • ๐Ÿ› ๏ธ Microservices in Python without the complexity of gRPC or REST frameworks
  • ๐Ÿ“ก Inter-process communication (IPC) made simple and Pythonic
  • ๐Ÿ”Œ Remote procedure calls (RPC) without learning new protocols

Why remotefunc?

The Problem: You have two Python processes that need to share data or call each other's functions. Traditional solutions are complicated:

  • Files? Slow and error-prone
  • Databases? Overkill for simple communication
  • Sockets? Too low-level
  • Message queues (RabbitMQ, Redis)? Too heavy
  • multiprocessing.Queue? Only works with parent/child processes
  • REST APIs? Too much boilerplate

The Solution: With remotefunc, just add one decorator and import functions normally. That's it.

Features

โœจ Zero Configuration - Server starts automatically, no setup required
๐ŸŽฏ Transparent RPC - Remote calls look identical to local calls
๐Ÿ”’ Type Safe - Full support for type hints and IDE autocomplete
โšก Fast - HTTP-based with smart JSON/pickle serialization
๐Ÿ› Great Debugging - Remote exceptions include full tracebacks
๐Ÿชถ Lightweight - No external dependencies, pure Python
๐Ÿ”„ Stateful - Share data structures across processes easily
๐Ÿ“ฆ Works Everywhere - Any Python 3.7+ on Windows, macOS, Linux

Use Cases

1. Daemon + Controller Pattern

Perfect for background services controlled by CLI tools:

# daemon.py - runs continuously
@shared
def start_task(name): ...

@shared  
def get_status(): ...

# cli.py - user commands
from daemon import start_task, get_status
start_task("backup")
print(get_status())

2. Multi-Process Data Sharing

Share state between independent Python processes:

# data_server.py
cache = {}

@shared
def set(key, value):
    cache[key] = value

@shared
def get(key):
    return cache.get(key)

# Any other process can now access the shared cache
from data_server import set, get
set("user_123", {"name": "Alice"})

3. Distributed Task Processing

Coordinate work across multiple Python processes:

# coordinator.py
jobs = []

@shared
def submit_job(task):
    jobs.append(task)
    return len(jobs)

# worker.py
from coordinator import submit_job
submit_job({"type": "process_video", "file": "video.mp4"})

4. Real-time Monitoring

Monitor long-running processes from separate scripts:

# long_process.py
progress = 0

@shared
def get_progress():
    return progress

# monitor.py
from long_process import get_progress
while True:
    print(f"Progress: {get_progress()}%")
    time.sleep(1)

How It Works

  1. Decorator Registration: @shared registers your function and starts an HTTP server (first time only)
  2. Smart Detection: When imported from another process, creates a remote proxy
  3. HTTP Communication: Client makes POST request โ†’ Server executes function โ†’ Returns result
  4. Transparent Errors: Exceptions are serialized and re-raised on the client side
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”         HTTP POST          โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚  Client Process โ”‚  โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€>  โ”‚  Server Process โ”‚
โ”‚                 โ”‚                             โ”‚                 โ”‚
โ”‚  from daemon    โ”‚   {"function": "push",     โ”‚  @shared        โ”‚
โ”‚  import func    โ”‚    "args": [item]}         โ”‚  def push():    โ”‚
โ”‚                 โ”‚                             โ”‚      items.add  โ”‚
โ”‚  func(item)     โ”‚  <โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€  โ”‚      return len โ”‚
โ”‚                 โ”‚   {"result": 1}            โ”‚                 โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜                             โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

API Reference

@shared

Make any function callable from other processes.

from remotefunc import shared

@shared
def my_function(x: int, y: int) -> int:
    """Full type hints and docstrings work perfectly"""
    return x + y

configure(host=None, port=None)

Configure global settings for remote calls.

from remotefunc import configure

# Call this in the client process before importing shared functions
configure(host='192.168.1.10', port=8080)

get_server_port()

Get the current server port (default: 5555).

from remotefunc import get_server_port
print(f"Server running on port {get_server_port()}")

shutdown_server()

Gracefully shutdown the server.

from remotefunc import shutdown_server
shutdown_server()

Advanced Usage

Custom Port

from remotefunc.server import start_server

start_server(port=8080)  # Start before decorating functions

@shared
def my_function():
    pass

Error Handling

Remote exceptions are propagated with full context:

from daemon import risky_function
from remotefunc.client import RemoteCallError

try:
    result = risky_function()
except RemoteCallError as e:
    print(f"Remote call failed: {e}")
    # Full traceback from the server process is included!

Complex Data Types

Works with JSON-serializable data and falls back to pickle:

@shared
def process_data(data: dict, callback: callable = None):
    # Dicts, lists, primitives โ†’ JSON (fast)
    # Complex objects โ†’ pickle (automatic)
    return result

Comparison with Alternatives

Solution Setup Complexity Use Case remotefunc Equivalent
Files/JSON Low Slow data sharing โœ… Just use @shared
Sockets High Custom protocols โœ… Just use @shared
multiprocessing.Queue Medium Parent-child only โœ… Works with any processes
Redis/RabbitMQ Very High Production scale โŒ Use those for production
REST API (Flask) High HTTP services โœ… But with zero boilerplate
gRPC Very High Performance critical โŒ Use gRPC for that
XML-RPC Medium Legacy systems โœ… Modern Python approach

FAQ

Q: How do two processes discover each other?
A: The server automatically starts on localhost:5555. Client imports create proxies that connect to this address.

Q: What if the server process isn't running?
A: You'll get a clear RemoteCallError indicating connection failure.

Q: Can I use this in production?
A: It's great for internal tools, daemons, and development. For production microservices, consider gRPC or proper REST APIs with authentication.

Q: Does it work with threading/asyncio?
A: Yes! The server is multi-threaded and can handle concurrent requests. Async functions need to be wrapped with asyncio.run().

Security Warning โš ๏ธ

remotefunc uses pickle as a fallback serialization mechanism for complex Python objects.

NEVER use this library across untrusted networks or to communicate with untrusted clients.

An attacker who can send data to the remotefunc server (default port 5555) can execute arbitrary code on your machine. This library is designed for localhost communication or within a strictly secured, trusted private network.

Examples

See the examples/ directory:

  • daemon.py - Full-featured server with multiple shared functions
  • controller.py - Client demonstrating all remote call patterns

Contributing

Contributions welcome! Please open an issue or PR on GitHub.

License

MIT License - see LICENSE.md file for details.

Keywords for Search

python ipc python rpc inter process communication python share data between python processes python process communication python remote function call python daemon controller python distributed call function in another process python python multiprocessing communication python process synchronization


Made with โค๏ธ for developers who want IPC/RPC to "just work"

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

remotefunc-0.1.0.tar.gz (16.5 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

remotefunc-0.1.0-py3-none-any.whl (11.4 kB view details)

Uploaded Python 3

File details

Details for the file remotefunc-0.1.0.tar.gz.

File metadata

  • Download URL: remotefunc-0.1.0.tar.gz
  • Upload date:
  • Size: 16.5 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.3

File hashes

Hashes for remotefunc-0.1.0.tar.gz
Algorithm Hash digest
SHA256 678663489f9bd24c3e0c934fa8a2712e3b13e12f09dbb59c724386ef5d376e7e
MD5 9ab27690bdb4e4c9b117de706971ab14
BLAKE2b-256 dda05788e11e725494494099730ecd6841ae19b7851020542109e577e9847950

See more details on using hashes here.

File details

Details for the file remotefunc-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: remotefunc-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 11.4 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.3

File hashes

Hashes for remotefunc-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 9773c9544cda54b21fac9ccb27131420aaff8daa80525d4f05f9859b67cc594c
MD5 54ca96a9ae533044118c59d07b34ef30
BLAKE2b-256 6d8dacb0acb1e0d10c7c5247e4ac4d4b79452a08cc9e3c2e8febde4734b7a147

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page