Skip to main content

remotepy

remotepy is a powerful RPC (Remote Procedure Call) framework that lets you write Python functions and call them remotely from JavaScript, C#, or Python over WebSockets.


Table of contents

  1. Features
  2. Installation
  3. Quick-start (5 minutes, no database)
  4. Automated setup wizard
  5. Session management — choosing a backend
  6. MySQL setup guide
  7. Advanced features
  8. Client examples
  9. Configuration reference
  10. Security features
  11. API reference
  12. Best practices
  13. Troubleshooting

Features

  • Multi-language support — call Python from JavaScript (browser), C#, or Python
  • Decorator API — expose functions with @remotepy_func / @remotepy_class
  • Session management — built-in, works with or without MySQL
  • In-memory sessions — zero-dependency mode, no database needed
  • MySQL sessions — persistent sessions backed by MySQL
  • Pluggable storage — bring your own session backend (Redis, SQLite, etc.)
  • Async / streamingasync def, generators, async generators
  • CPU-bound work@cpu_bound runs heavy tasks in a ProcessPoolExecutor
  • SSL/TLSrun_ssl() for secure wss:// connections
  • Pub/SubPubSubBroadcastServerFactory for real-time broadcasting
  • Security — rate limiting, input validation, password sanitization in logs
  • Setup wizardremotepy-setup generates a working server in seconds

Installation

Without MySQL (in-memory sessions)

pip install remotepy

With MySQL support

pip install remotepy[mysql]

Quick-start — no database

You can run a full session-managed server with zero external dependencies:

# server.py
from remotepy import *
from remotepy.session.SimpleSessionServer import SimpleSessionServer


@remotepy_class
class MyServer(WebSocketRPCServerProtocol, SimpleSessionServer):

    def __init__(self):
        super().__init__()
        # Seed users programmatically — or call self.load_users_from_env()
        self.add_user("alice", "password123", "alice@example.com")
        self.add_user("bob",   "s3cret",      "bob@example.com")

    def onConnect(self, request):
        print("Client connecting:", request.peer)

    @remotepy_method
    def hello(self, name):
        """Say hello."""
        return f"Hello, {name}!"

    def onClose(self, wasClean, code, reason):
        print("Client closed:", code, reason)


if __name__ == "__main__":
    import logging
    logging.basicConfig(level=logging.INFO)
    server = MyServer()
    server.run("0.0.0.0", 8082)

Run it:

python server.py

Automated setup wizard

The fastest way to get started:

pip install remotepy
remotepy-setup

The wizard:

  1. Asks whether you want in-memory or MySQL session storage
  2. Generates a ready-to-run server.py
  3. Generates an .env.example with all settings documented
  4. (MySQL only) generates schema.sql to create all required tables
  5. (MySQL only) optionally generates docker-compose.yml for local dev MySQL

Session management

remotepy provides three ways to handle sessions. Pick what fits your project:

Option 1 — In-memory, no database (simplest)

Use SimpleSessionServer. Zero setup, zero dependencies beyond remotepy itself. Users and sessions are stored in RAM — state is lost on restart.

Best for: development, prototyping, small apps, microservices.

from remotepy import *
from remotepy.session.SimpleSessionServer import SimpleSessionServer

@remotepy_class
class MyServer(WebSocketRPCServerProtocol, SimpleSessionServer):
    def __init__(self):
        super().__init__()
        self.add_user("admin", "secret", "admin@example.com")

Load users from an environment variable instead of hardcoding them:

export REMOTEPY_USERS="admin:secret:admin@example.com,guest:guest:guest@example.com"
def __init__(self):
    super().__init__()
    self.load_users_from_env()

Option 2 — Custom auth, in-memory sessions (flexible)

Inherit from SessionServer with db_config=None and override _authenticate_user:

from remotepy import *

@remotepy_class
class MyServer(WebSocketRPCServerProtocol, SessionServer):
    def __init__(self):
        super().__init__(None)   # None → InMemorySessionStorage

    def _authenticate_user(self, username: str, password: str) -> bool:
        # Your own auth logic — check a file, API, LDAP, etc.
        return username == "admin" and password == "secret"

    @remotepy_method
    def hello(self, name):
        return f"Hello, {name}!"

Option 3 — MySQL (production)

Full persistent sessions + user management:

from remotepy import *

@remotepy_class
class MyServer(WebSocketRPCServerProtocol, SessionServer):
    def __init__(self):
        super().__init__(db_config={
            "host":     "localhost",
            "user":     "remotepy",
            "password": "changeme",
            "database": "myschema",
        }, use_schema_name="myschema")
        self.set_email_config()  # reads REMOTEPY_EMAIL_* env vars

Option 4 — Custom storage backend

Implement SessionStorageBackend and pass it directly:

from remotepy import *
from remotepy.session.storage.base import SessionStorageBackend

class RedisSessionStorage(SessionStorageBackend):
    # ... implement all abstract methods ...

@remotepy_class
class MyServer(WebSocketRPCServerProtocol, SessionServer):
    def __init__(self):
        super().__init__(storage_backend=RedisSessionStorage("redis://localhost"))

MySQL setup guide

Step 1 — Install with MySQL extra

pip install remotepy[mysql]

Step 2 — Create the schema

Use the automated wizard (recommended):

remotepy-setup
# Choose option 2 (MySQL)
# This generates schema.sql automatically

Or run the schema manually:

mysql -u root -p < schema.sql

The schema creates these tables in your chosen database:

Table Purpose
session_state One row per active WebSocket connection
session_variable_blob Key-value store for session variables
new_session_ids One-time session tokens
user User accounts (username, bcrypt password, email, address)
address Postal addresses linked to users

Step 3 — Local dev with Docker

The setup wizard generates a docker-compose.yml. Start MySQL with:

docker compose up -d

Credentials default to: user remotepy, password changeme, port 3306.

Step 4 — Configure via .env

Copy .env.example to .env and fill in your values:

DB_HOST=localhost
DB_USER=remotepy
DB_PASSWORD=changeme
DB_NAME=myschema

REMOTEPY_EMAIL_USER=your@email.com
REMOTEPY_EMAIL_PASSWORD=app-password
REMOTEPY_EMAIL_SERVER=smtp.gmail.com
REMOTEPY_EMAIL_PORT=587
REMOTEPY_RESET_PASSWORD_EMAIL=noreply@yourdomain.com
REMOTEPY_DOMAIN_NAME=https://www.yourdomain.com

Advanced features

Async functions

@remotepy_class
class AsyncServer(WebSocketRPCServerProtocol):

    @remotepy_func
    async def fetch_data(self, url):
        import aiohttp
        async with aiohttp.ClientSession() as s:
            async with s.get(url) as r:
                return await r.json()

Streaming with generators

@remotepy_func
def stream_rows(self, count):
    for i in range(count):
        yield {"index": i, "data": f"item_{i}"}

@remotepy_func
async def stream_async(self, count):
    for i in range(count):
        await asyncio.sleep(0.05)
        yield {"index": i, "data": f"item_{i}"}

CPU-bound work

from remotepy import *
import numpy as np

@remotepy_class
class MLServer(WebSocketRPCServerProtocol):

    @remotepy_method
    @cpu_bound              # runs in ProcessPoolExecutor — bypasses the GIL
    def run_inference(self, data):
        arr = np.array(data)
        return heavy_model(arr).tolist()

    @remotepy_method        # runs in ThreadPoolExecutor (default)
    def get_status(self):
        return {"status": "ok"}

Decorator order matters: @cpu_bound must be below @remotepy_method / @remotepy_func.

Your function does… Use
Database queries, HTTP calls, file I/O async def with await
Lightweight sync logic def (thread pool)
numpy, pandas, ML inference, image processing def + @cpu_bound
LLM streaming async def with yield

SSL/TLS

server = MyServer()
server.run_ssl(
    "0.0.0.0", 8443,
    "/etc/ssl/private/server.key",
    "/etc/ssl/certs/fullchain.pem",
)

Protected functions

from remotepy.websocket.remotepy import remotepy_login_required, remotepy_permitted_to

@remotepy_class
class ProtectedServer(WebSocketRPCServerProtocol, SessionServer):

    @remotepy_func
    @remotepy_login_required
    def sensitive_data(self):
        return {"secret": "data"}

    @remotepy_func
    @remotepy_permitted_to("admin")
    def admin_action(self):
        return {"ok": True}

Pub/Sub broadcasting

from remotepy import PubSubBroadcastServerFactory

server = MyServer()
server.run("0.0.0.0", 8082, ServerFactory=PubSubBroadcastServerFactory)

Client examples

JavaScript

<script src="js/remotepy.1.0.0.min.js"></script>
<script>
    var RemotePy = new RemotePyClient();

    window.onload = function() {
        RemotePy.serverName = 'ws://localhost:8082';
        RemotePy.start();
    };

    RemotePy.onopen = function() {
        RemotePy.MyServer.hello("World", function(result) {
            console.log(result);   // "Hello, World!"
        });
    };
</script>

Python

pip install remotepy_client
from remotepy_client.remotepy_rpc_client import RemotePyRPCClientSync

client = RemotePyRPCClientSync("ws://localhost:8082", verbose=False)
client.buildService('')
MyServer = client.getService('MyServer')("ws://localhost:8082", False)

result = MyServer.hello(name="Python", callback=None)
print(result)   # "Hello, Python!"

client.thread().join()

Configuration reference

Environment variables

Variable Default Description
REMOTEPY_EMAIL_USER SMTP user for password-reset emails
REMOTEPY_EMAIL_PASSWORD SMTP password
REMOTEPY_EMAIL_SERVER smtp-relay.sendinblue.com SMTP server
REMOTEPY_EMAIL_PORT 587 SMTP port
REMOTEPY_RESET_PASSWORD_EMAIL info@kubloy.com From address for reset emails
REMOTEPY_DOMAIN_NAME http://www.alpharithmic.com Base URL for reset links
REMOTEPY_USERS user:pass:email,... for SimpleSessionServer

Rate limiting

Default: 100 calls per function per 60 seconds. Customise:

server._rate_limit_window = 60     # seconds
server._rate_limit_max_calls = 200

Security features

  • Rate limiting — per-function call-rate cap (default 100/min)
  • Input validation — function names and args are validated before dispatch
  • Password sanitization — passwords are redacted from all log messages and errors
  • Bcrypt hashing — all user passwords are stored as bcrypt hashes
  • Single-use session tokensnew_session_ids tokens are consumed on first use
  • SQL injection protection — schema names are sanitized; all queries use parameterized args

API reference

Decorators

Decorator Description
@remotepy_class Makes a class a remotepy server
@remotepy_func Exposes a function for remote calls
@remotepy_method Same as @remotepy_func, used with SessionServer
@cpu_bound Runs in ProcessPoolExecutor (stacks below @remotepy_method)
@remotepy_login_required Requires authenticated session
@remotepy_permitted_to(action) Requires specific permission

Server methods

Method Description
server.run(ip, port) Start plain WebSocket server
server.run_ssl(ip, port, key, cert) Start TLS WebSocket server

SessionServer RPC methods (all storage backends)

Method Description
getNewSessionId() Generate a one-time session token
startSessionIfNotStarted(sessionid) Start session tracking
isLoggedIn(sessionid) Check auth status
validateLogin(sessionid, username, password, remember, currentUrl, afterLoginUrl) Authenticate
logOut() De-authenticate current session
getSessionId() Return current session ID

SessionServer RPC methods (MySQL or SimpleSessionServer)

Method Description
registerLogin(sessionid, username, password, first, middle, last, email, street, city, country) Register new user
registerLoginShort(sessionid, username, password, email) Register (email + username only)
checkIfUsernameExists(username) Check if username/email is taken
forgotPassword(sessionid, email) Send password-reset email
resetPassword(sessionid, code, new_password, repeat_password) Apply reset
getUserProfile(sessionid) Get logged-in user's profile
updateUserProfile(sessionid, ...) Update profile

SimpleSessionServer extra methods (non-RPC)

Method Description
add_user(username, plain_password, email, ...) Add a user before run()
load_users_from_env() Load users from REMOTEPY_USERS env var

Storage backends

Class Import Notes
InMemorySessionStorage remotepy.session.storage.memory No dependencies, RAM-only
MySQLSessionStorage remotepy.session.storage.mysql Requires remotepy[mysql]
SessionStorageBackend (ABC) remotepy.session.storage.base Base for custom backends

Best practices

  1. Choose the right session backend early — in-memory for dev, MySQL for prod
  2. Use SimpleSessionServer for apps that don't need a database at all
  3. Use SSL in production — always run_ssl() in production environments
  4. Store config in .env — never hardcode passwords in source code
  5. Use async def for I/O and def + @cpu_bound for heavy computation
  6. Adjust rate limits to match your workload
  7. Override _authenticate_user to integrate with existing auth systems

Troubleshooting

"MySQLSessionStorage requires the 'mysqleasy' package"

Install the MySQL extra:

pip install remotepy[mysql]

"registerLogin requires MySQL storage"

You are calling a user-management method on a server with in-memory session storage. Either:

  • Switch to SimpleSessionServer for full in-memory user management, or
  • Pass a db_config to use MySQL storage

Rate limit errors

server._rate_limit_max_calls = 500   # increase cap

Connection issues

  • Confirm the server is running: python server.py
  • Check firewall rules for the port
  • WebSocket URL format: ws://host:port (plain) or wss://host:port (TLS)

Documentation

For more information, visit https://www.remotepy.com

License

Proprietary software. All rights reserved. See the LICENSE file for details.

Author

Faraz Farukh Tambolifaraz.tamboli@gmail.com

Download files

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

Source Distributions

No source distribution files available for this release.See tutorial on generating distribution archives.

Built Distributions

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

remotepy-0.3.1-cp312-cp312-win_amd64.whl (847.4 kB view details)

Uploaded CPython 3.12Windows x86-64

remotepy-0.3.1-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl (6.7 MB view details)

Uploaded CPython 3.12manylinux: glibc 2.17+ x86-64

remotepy-0.3.1-cp311-cp311-win_amd64.whl (867.1 kB view details)

Uploaded CPython 3.11Windows x86-64

remotepy-0.3.1-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl (6.7 MB view details)

Uploaded CPython 3.11manylinux: glibc 2.17+ x86-64

remotepy-0.3.1-cp310-cp310-win_amd64.whl (863.5 kB view details)

Uploaded CPython 3.10Windows x86-64

remotepy-0.3.1-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.whl (6.4 MB view details)

Uploaded CPython 3.10manylinux: glibc 2.17+ x86-64

remotepy-0.3.1-cp39-cp39-win_amd64.whl (855.2 kB view details)

Uploaded CPython 3.9Windows x86-64

remotepy-0.3.1-cp39-cp39-manylinux2014_x86_64.manylinux_2_17_x86_64.whl (6.3 MB view details)

Uploaded CPython 3.9manylinux: glibc 2.17+ x86-64

File details

Details for the file remotepy-0.3.1-cp312-cp312-win_amd64.whl.

File metadata

  • Download URL: remotepy-0.3.1-cp312-cp312-win_amd64.whl
  • Upload date:
  • Size: 847.4 kB
  • Tags: CPython 3.12, Windows x86-64
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/7.0.0 CPython/3.13.9

File hashes

Hashes for remotepy-0.3.1-cp312-cp312-win_amd64.whl
Algorithm Hash digest
SHA256 3d4bab6e5777bc34c118819a573b99881214f2def4ae4fa8f679a5ff73ac7f19
MD5 66a24458ec939a5f575a952b6dad771a
BLAKE2b-256 8cbb9bd692702dc44e02ef37a034eff176cc9fd056f272c56274d9d757534560

See more details on using hashes here.

File details

Details for the file remotepy-0.3.1-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl.

File metadata

File hashes

Hashes for remotepy-0.3.1-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl
Algorithm Hash digest
SHA256 66c7dc5ea6b7ff1390a1d2dc3d71bf0f0540c0e7bab6e771f6490a69471f9d35
MD5 dc5a26efebf51d2793e0154c40424220
BLAKE2b-256 81275a3626dbdbda300746a4ccfc11bbce20baa8b574279383de8c5bd9594e3b

See more details on using hashes here.

File details

Details for the file remotepy-0.3.1-cp311-cp311-win_amd64.whl.

File metadata

  • Download URL: remotepy-0.3.1-cp311-cp311-win_amd64.whl
  • Upload date:
  • Size: 867.1 kB
  • Tags: CPython 3.11, Windows x86-64
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/7.0.0 CPython/3.13.9

File hashes

Hashes for remotepy-0.3.1-cp311-cp311-win_amd64.whl
Algorithm Hash digest
SHA256 b0bf6dcdfc3751efbcf6b91b2018eb536fe3bdccc636816d32620105593cc968
MD5 8a1958cc6469ac1f20ed94d9a07e1e98
BLAKE2b-256 f789f5745c9de27a1e17c5deb0ec29730997e9f24aa399376f5b7abefbc0e546

See more details on using hashes here.

File details

Details for the file remotepy-0.3.1-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl.

File metadata

File hashes

Hashes for remotepy-0.3.1-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl
Algorithm Hash digest
SHA256 150600decb0493a31de877b0ec1ba52e8e4abeffe5d179766ed2474535734484
MD5 d4bde7d5517c7e238657000efa985e7b
BLAKE2b-256 2f9157bd04792e8f0d8d0fd177337b9b7a6858e2219a4e5738b1c3f34c742e2b

See more details on using hashes here.

File details

Details for the file remotepy-0.3.1-cp310-cp310-win_amd64.whl.

File metadata

  • Download URL: remotepy-0.3.1-cp310-cp310-win_amd64.whl
  • Upload date:
  • Size: 863.5 kB
  • Tags: CPython 3.10, Windows x86-64
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/7.0.0 CPython/3.13.9

File hashes

Hashes for remotepy-0.3.1-cp310-cp310-win_amd64.whl
Algorithm Hash digest
SHA256 73d7d1830c0ef1784d3c4fd36819ab1d8cd641849c8ba0d1b73c489b5dbe86e7
MD5 427296f810fd6d41b10376429ae27757
BLAKE2b-256 31320fbbfa68f2b2bd7cce3071df7e8ddfa202fd04a0c38770ab0e27af0f5db9

See more details on using hashes here.

File details

Details for the file remotepy-0.3.1-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.whl.

File metadata

File hashes

Hashes for remotepy-0.3.1-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.whl
Algorithm Hash digest
SHA256 f353c0dfcd459472afa27184ef26ea976e589ea0fd4755148b1d553d2174ff63
MD5 86abb2366717ee8b5a452435741ae771
BLAKE2b-256 7a81184abee4c3218f53754729fcc3e928d72fffc6ed7e8ef8d45dba5f4a70e9

See more details on using hashes here.

File details

Details for the file remotepy-0.3.1-cp39-cp39-win_amd64.whl.

File metadata

  • Download URL: remotepy-0.3.1-cp39-cp39-win_amd64.whl
  • Upload date:
  • Size: 855.2 kB
  • Tags: CPython 3.9, Windows x86-64
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/7.0.0 CPython/3.13.9

File hashes

Hashes for remotepy-0.3.1-cp39-cp39-win_amd64.whl
Algorithm Hash digest
SHA256 baba4f9444d26b6ff2b9c32c46b83a19dec6f5e8535aac3ec54cf87246e13142
MD5 20089e4db4529e859b05d0c8b87bf42a
BLAKE2b-256 893bd2583ea55390a0e9a1408ba970219d60c86f7b959f949f5eb7317df7a1e1

See more details on using hashes here.

File details

Details for the file remotepy-0.3.1-cp39-cp39-manylinux2014_x86_64.manylinux_2_17_x86_64.whl.

File metadata

File hashes

Hashes for remotepy-0.3.1-cp39-cp39-manylinux2014_x86_64.manylinux_2_17_x86_64.whl
Algorithm Hash digest
SHA256 82082efda5bf3a6aabb3896b3a34cad6351c3dd01e1f7d13ced67d61025ed40e
MD5 884acfeed12e06edb946f143878d255b
BLAKE2b-256 49903de66d7f32693158142972f17fa3028019cdc090581c02a35708e5d9252e

See more details on using hashes here.

Release history Release notifications | RSS feed

0.3.2

8 files

This release

0.3.1 This release

8 files

0.3.0

8 files

0.2.0

8 files

0.0.3

8 files

0.0.2

8 files

0.0.1

8 files

0.0.0

2 files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page