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

Uploaded CPython 3.12Windows x86-64

remotepy-0.3.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl (6.6 MB view details)

Uploaded CPython 3.12manylinux: glibc 2.17+ x86-64

remotepy-0.3.0-cp311-cp311-win_amd64.whl (850.2 kB view details)

Uploaded CPython 3.11Windows x86-64

remotepy-0.3.0-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl (6.5 MB view details)

Uploaded CPython 3.11manylinux: glibc 2.17+ x86-64

remotepy-0.3.0-cp310-cp310-win_amd64.whl (846.9 kB view details)

Uploaded CPython 3.10Windows x86-64

remotepy-0.3.0-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.whl (6.2 MB view details)

Uploaded CPython 3.10manylinux: glibc 2.17+ x86-64

remotepy-0.3.0-cp39-cp39-win_amd64.whl (839.2 kB view details)

Uploaded CPython 3.9Windows x86-64

remotepy-0.3.0-cp39-cp39-manylinux2014_x86_64.manylinux_2_17_x86_64.whl (6.1 MB view details)

Uploaded CPython 3.9manylinux: glibc 2.17+ x86-64

File details

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

File metadata

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

File hashes

Hashes for remotepy-0.3.0-cp312-cp312-win_amd64.whl
Algorithm Hash digest
SHA256 06cc9f84165b86e2875c74c16d3c20be2faddf298ddec4001cdc5b835bd6bc98
MD5 1123f4d8dcbfac1a21437cb06a86deee
BLAKE2b-256 8a7ce998761dca9e0c34d4474f7548849d27c992de3ff859ad3bd3e55ab529c9

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for remotepy-0.3.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl
Algorithm Hash digest
SHA256 d991b575aca6e7f7180c444688b894b328820e9e60a3275b1ef5317836f3a57a
MD5 a52d89478221d832903f38639953ae52
BLAKE2b-256 8abca999730fd0197ab811455b2184f4b9c5a6934ab0e6cdfb2e02b0f66954a2

See more details on using hashes here.

File details

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

File metadata

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

File hashes

Hashes for remotepy-0.3.0-cp311-cp311-win_amd64.whl
Algorithm Hash digest
SHA256 741e220c4da022d1c2d9e7252a86bb6beaf5a2fcb041d542ae97a8b43dca6753
MD5 ffef559b76ee68c00938ea6635de1ec3
BLAKE2b-256 72618cc9531ac85096d63bbe8e513912cdf84e1009abafc2db0f374494368e28

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for remotepy-0.3.0-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl
Algorithm Hash digest
SHA256 701e8676edcabb1c8fdab75f2ef5a2b6b460d95f1448923f81691c85e52e0b14
MD5 dee220a34fed9261913e34b41d997eb5
BLAKE2b-256 fd338058f2199d63f81ed53e2c362187b04467e5d38bd2fba14a3565fc91e942

See more details on using hashes here.

File details

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

File metadata

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

File hashes

Hashes for remotepy-0.3.0-cp310-cp310-win_amd64.whl
Algorithm Hash digest
SHA256 cf7dda26100dcffccc75155c52f1348a5ff89d82c13a9502f36511a943ebfa46
MD5 b2480c53923e914d41d4579cea55dc14
BLAKE2b-256 dfcf3150716770739abfd40e0f044ed26d64e4f1226dda672e217f916f509482

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for remotepy-0.3.0-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.whl
Algorithm Hash digest
SHA256 373d9a02624e72106d58ead361ad989e53c2989c123029505753741a71fca865
MD5 e681c9672940ed239bae5236512c594d
BLAKE2b-256 2de22c7c6d7840cf23a62b6e6b22ff15a45c732c3056a1b8397b84237717b412

See more details on using hashes here.

File details

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

File metadata

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

File hashes

Hashes for remotepy-0.3.0-cp39-cp39-win_amd64.whl
Algorithm Hash digest
SHA256 a9c6d8acd18a03f24d8ca72ac33569379c848677a1f9a94bf5cb7ce5d335e52d
MD5 ed4fd18a1a0b7d9592a8acf24faeb653
BLAKE2b-256 6b3d2fbda513831ad58551b2bb3160920160ccfe1f7a8072a323988cf0fb2a02

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for remotepy-0.3.0-cp39-cp39-manylinux2014_x86_64.manylinux_2_17_x86_64.whl
Algorithm Hash digest
SHA256 32aa9d591fc14e1844b090648fe6452bec51b34405ed71bf8a428020dc10b2d3
MD5 4b2aa7518627f91ae3225a11c88ee1a2
BLAKE2b-256 e06c2b12e623c0431f551e7a77448dc385d16e8ff4022eb14b21ff8243ffadb3

See more details on using hashes here.

Release history Release notifications | RSS feed

0.3.2

8 files

0.3.1

8 files

This release

0.3.0 This release

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