Skip to main content

remotepy allows Python functions to be called remotely from multiple languages including JavaScript, CSharp and Python

Project description

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

Project details


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

Uploaded CPython 3.12Windows x86-64

remotepy-0.2.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl (6.5 MB view details)

Uploaded CPython 3.12manylinux: glibc 2.17+ x86-64

remotepy-0.2.0-cp311-cp311-win_amd64.whl (840.8 kB view details)

Uploaded CPython 3.11Windows x86-64

remotepy-0.2.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.2.0-cp310-cp310-win_amd64.whl (838.0 kB view details)

Uploaded CPython 3.10Windows x86-64

remotepy-0.2.0-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.whl (6.1 MB view details)

Uploaded CPython 3.10manylinux: glibc 2.17+ x86-64

remotepy-0.2.0-cp39-cp39-win_amd64.whl (830.1 kB view details)

Uploaded CPython 3.9Windows x86-64

remotepy-0.2.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.2.0-cp312-cp312-win_amd64.whl.

File metadata

  • Download URL: remotepy-0.2.0-cp312-cp312-win_amd64.whl
  • Upload date:
  • Size: 820.1 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.2.0-cp312-cp312-win_amd64.whl
Algorithm Hash digest
SHA256 32feddc6898825018f101bfea9114f2677433ab46574f9fa19c0b560d2f0bf28
MD5 e6f63011ce5a6ed7529fcbaf24a72ec2
BLAKE2b-256 48cb617bc081b2910be8460052381674fdaf1b18e3a81a12cc7a83f70dc75389

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for remotepy-0.2.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl
Algorithm Hash digest
SHA256 b4b7bf614375ea1a50fd3ee94b9bacfcf5fceca3d103b0378239f3cb9257a3b2
MD5 c388456ab2dbd4d2a377c2397657d67c
BLAKE2b-256 ebe0fcd1c20c6ba0f7d3acba6f2d61de48d2b8c1d83d5acf5c7ba8566064b6ff

See more details on using hashes here.

File details

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

File metadata

  • Download URL: remotepy-0.2.0-cp311-cp311-win_amd64.whl
  • Upload date:
  • Size: 840.8 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.2.0-cp311-cp311-win_amd64.whl
Algorithm Hash digest
SHA256 fc3d884103e4ee6d34ddb2f5495f678b6c040130177062adaf847c325bfbc93e
MD5 70991a21e80b116ad4facf419f336bc8
BLAKE2b-256 9aa6f51eab8ed9a173762d9bf04aac7ec1dbf8754ea320e9bce24e04bb500a3a

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for remotepy-0.2.0-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl
Algorithm Hash digest
SHA256 54c59cb4fb3ae1598462cadbd2baa66ecd2a96d3e75e7e7082f9733c8590cbaf
MD5 eb27aad4205f8e87547509af6545f6bf
BLAKE2b-256 1dbbf91239be13f447d1bc14112897cee97735a874edbf12652f742f26d9a1db

See more details on using hashes here.

File details

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

File metadata

  • Download URL: remotepy-0.2.0-cp310-cp310-win_amd64.whl
  • Upload date:
  • Size: 838.0 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.2.0-cp310-cp310-win_amd64.whl
Algorithm Hash digest
SHA256 1ee9531aae5532ad0ffad050a81cdd630e3068b790c0e5da6db36667b3fe32fe
MD5 92b69e2388a78208560fe4363d044e3d
BLAKE2b-256 fbe338534a19858be425e3e6c9d8781f7ad0be1898028aaa491ec5d6eb44c2c5

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for remotepy-0.2.0-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.whl
Algorithm Hash digest
SHA256 60e37d8780333b9e728cfa21d1ef84c3f38ba79ecd561cc9c90725c77fa066a9
MD5 be13db86e7a30e19524a66e92cad2307
BLAKE2b-256 d32ec3557db246473493be7129ff08bc4931b92675af70185c6d0c67448f0c2f

See more details on using hashes here.

File details

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

File metadata

  • Download URL: remotepy-0.2.0-cp39-cp39-win_amd64.whl
  • Upload date:
  • Size: 830.1 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.2.0-cp39-cp39-win_amd64.whl
Algorithm Hash digest
SHA256 16459ac7a8c59c78553627d6df357e27dae1d7ea11845f170b4fc182ecb974e6
MD5 af3dd643e51074039542dfa78723d055
BLAKE2b-256 fafa92b8d6b0867c4c0b80a65a9470298a7c8d28af76afcf9d79db5cda5a5e9e

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for remotepy-0.2.0-cp39-cp39-manylinux2014_x86_64.manylinux_2_17_x86_64.whl
Algorithm Hash digest
SHA256 e652c7ef1a45670a47e24296a6eee028d5a0eea6e135650a88da1af6091f45d3
MD5 83c1d6a0d07b1e6e3ca0d42c7a98b127
BLAKE2b-256 8f04f05b9ee9c59db8db8d1e159a978270082da0d06236f66a03484d1c5fc877

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