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.2-cp312-cp312-win_amd64.whl (851.9 kB view details)

Uploaded CPython 3.12Windows x86-64

remotepy-0.3.2-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl (6.8 MB view details)

Uploaded CPython 3.12manylinux: glibc 2.17+ x86-64

remotepy-0.3.2-cp311-cp311-win_amd64.whl (871.1 kB view details)

Uploaded CPython 3.11Windows x86-64

remotepy-0.3.2-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl (6.8 MB view details)

Uploaded CPython 3.11manylinux: glibc 2.17+ x86-64

remotepy-0.3.2-cp310-cp310-win_amd64.whl (867.3 kB view details)

Uploaded CPython 3.10Windows x86-64

remotepy-0.3.2-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.2-cp39-cp39-win_amd64.whl (859.0 kB view details)

Uploaded CPython 3.9Windows x86-64

remotepy-0.3.2-cp39-cp39-manylinux2014_x86_64.manylinux_2_17_x86_64.whl (6.4 MB view details)

Uploaded CPython 3.9manylinux: glibc 2.17+ x86-64

File details

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

File metadata

  • Download URL: remotepy-0.3.2-cp312-cp312-win_amd64.whl
  • Upload date:
  • Size: 851.9 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.2-cp312-cp312-win_amd64.whl
Algorithm Hash digest
SHA256 bb9d4274bc8f504435f3b41ebdb2635b4c67069c2b3b8338e1e6a75a90b13f81
MD5 017493e7ce476fcfa828dd17d3b662e5
BLAKE2b-256 a5faef77d81830a27bdf5233248a3486e7fbc9927c128e02c93cbdbb32c62c69

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for remotepy-0.3.2-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl
Algorithm Hash digest
SHA256 18a5fd09276c38e894a8d9274fb54636ca0889049e8f7932693222b4c61f81c2
MD5 1f50ce28faf381a854d2a93eed634bf7
BLAKE2b-256 d356d3d8cd0dac7676c732c94657deb7c1dfddb8b4b4309ae5342613ff1ba925

See more details on using hashes here.

File details

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

File metadata

  • Download URL: remotepy-0.3.2-cp311-cp311-win_amd64.whl
  • Upload date:
  • Size: 871.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.2-cp311-cp311-win_amd64.whl
Algorithm Hash digest
SHA256 776870d6cb3e245ac863e9eeca6244d549205dacc2141c54017109ff5ac8d44d
MD5 ec73f916c7c5ae3fba7cc30bb3c77c74
BLAKE2b-256 48e8b468274f196230cf7273ecf4554f9aa48c9609202b8fccdf3691f71488a4

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for remotepy-0.3.2-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl
Algorithm Hash digest
SHA256 f444013074332dd71dfb7fe8243bbf28fe33df16ad5f7eb3a17a9594e250ffba
MD5 ca35447ba823f24fc07a9d0440cf9216
BLAKE2b-256 803a3ab7069feedfe4bfd05a1c981ab3435898b1f61e23f193b60400492addd6

See more details on using hashes here.

File details

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

File metadata

  • Download URL: remotepy-0.3.2-cp310-cp310-win_amd64.whl
  • Upload date:
  • Size: 867.3 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.2-cp310-cp310-win_amd64.whl
Algorithm Hash digest
SHA256 760c3944c4a8ce7094f888ef9046816b4c303f9046fc3c351db61f2bf477abdb
MD5 79dde6f015e52c9f6d7824a1b02f6249
BLAKE2b-256 828caa555f66d39ae84588169bbbdc60bbb8494b31a97a36554ddf79ae2cf6ed

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for remotepy-0.3.2-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.whl
Algorithm Hash digest
SHA256 3c7fd172c8fa13b09f1da6e80c962fe10c67f43262fbdd42c333c453c3cde8b0
MD5 a83705f846bcb39708d60812ae1d6470
BLAKE2b-256 d1e72e5df1a83f13dc285338cff0b4f22560166f4deee030a96194e5261ba444

See more details on using hashes here.

File details

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

File metadata

  • Download URL: remotepy-0.3.2-cp39-cp39-win_amd64.whl
  • Upload date:
  • Size: 859.0 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.2-cp39-cp39-win_amd64.whl
Algorithm Hash digest
SHA256 75c49cde13f9accc91754084be68c97f17d7dd730473dd5cee2278a53ca45d62
MD5 4a4c1282a50eac7ae8848e7838be4568
BLAKE2b-256 8042e93a31b2db56ae2b1ad10326b46ff261aa6157b29e85e041872689041d20

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for remotepy-0.3.2-cp39-cp39-manylinux2014_x86_64.manylinux_2_17_x86_64.whl
Algorithm Hash digest
SHA256 02cc5fb96451bf63bb8da1681e1c50e5e57d98045f390c015acc193809f10b43
MD5 d9b0e2cc914490cf7dfabfa413e0b8b7
BLAKE2b-256 6b98e85023f20d82c3b501cbdd5876f38d193692b282b6a7d79baf31a19f6faa

See more details on using hashes here.

Release history Release notifications | RSS feed

This release

0.3.2 This release

8 files

0.3.1

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