WebSocket and WAMP in Python for Twisted and asyncio

Overview

Autobahn|Python

WebSocket & WAMP for Python on Twisted and asyncio.


Introduction

Autobahn|Python is a subproject of Autobahn and provides open-source implementations of

for Python 3.6+ and running on Twisted and asyncio.

You can use Autobahn|Python to create clients and servers in Python speaking just plain WebSocket or WAMP.

WebSocket allows bidirectional real-time messaging on the Web and beyond, while WAMP adds real-time application communication on top of WebSocket.

WAMP provides asynchronous Remote Procedure Calls and Publish & Subscribe for applications in one protocol running over WebSocket. WAMP is a routed protocol, so you need a WAMP Router to connect your Autobahn|Python based clients. We provide Crossbar.io, but there are other options as well.

Note

Autobahn|Python up to version v19.11.2 also supported Python 2 and 3.4+.

Features


Show me some code

To give you a first impression, here are two examples. We have lot more in the repo.

WebSocket Echo Server

Here is a simple WebSocket Echo Server that will echo back any WebSocket message received:

from autobahn.twisted.websocket import WebSocketServerProtocol
# or: from autobahn.asyncio.websocket import WebSocketServerProtocol

class MyServerProtocol(WebSocketServerProtocol):

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

    def onOpen(self):
        print("WebSocket connection open.")

    def onMessage(self, payload, isBinary):
        if isBinary:
            print("Binary message received: {} bytes".format(len(payload)))
        else:
            print("Text message received: {}".format(payload.decode('utf8')))

        # echo back message verbatim
        self.sendMessage(payload, isBinary)

    def onClose(self, wasClean, code, reason):
        print("WebSocket connection closed: {}".format(reason))

To actually run above server protocol, you need some lines of boilerplate.

WAMP Application Component

Here is a WAMP Application Component that performs all four types of actions that WAMP provides:

  1. subscribe to a topic
  2. publish an event
  3. register a procedure
  4. call a procedure
from autobahn.twisted.wamp import ApplicationSession
# or: from autobahn.asyncio.wamp import ApplicationSession

class MyComponent(ApplicationSession):

    @inlineCallbacks
    def onJoin(self, details):

        # 1. subscribe to a topic so we receive events
        def onevent(msg):
            print("Got event: {}".format(msg))

        yield self.subscribe(onevent, 'com.myapp.hello')

        # 2. publish an event to a topic
        self.publish('com.myapp.hello', 'Hello, world!')

        # 3. register a procedure for remote calling
        def add2(x, y):
            return x + y

        self.register(add2, 'com.myapp.add2')

        # 4. call a remote procedure
        res = yield self.call('com.myapp.add2', 2, 3)
        print("Got result: {}".format(res))

Above code will work on Twisted and asyncio by changing a single line (the base class of MyComponent). To actually run above application component, you need some lines of boilerplate and a WAMP Router.

Extensions

Networking framework

Autobahn runs on both Twisted and asyncio. To select the respective netoworking framework, install flavor:

  • asyncio: Install asyncio (when on Python 2, otherwise it's included in the standard library already) and asyncio support in Autobahn
  • twisted: Install Twisted and Twisted support in Autobahn

WebSocket acceleration and compression

  • accelerate: Install WebSocket acceleration - Only use on CPython - not on PyPy (which is faster natively)
  • compress: Install (non-standard) WebSocket compressors bzip2 and snappy (standard deflate based WebSocket compression is already included in the base install)

Encryption and WAMP authentication

Autobahn supports running over TLS (for WebSocket and all WAMP transports) as well as WAMP-cryposign authentication.

To install use this flavor:

  • encryption: Installs TLS and WAMP-cryptosign dependencies

Autobahn also supports WAMP-SCRAM authentication. To install:

  • scram: Installs WAMP-SCRAM dependencies

XBR

Autobahn includes support for XBR. To install use this flavor:

  • xbr:

To install:

pip install autobahn[xbr]

or (Twisted, with more bells an whistles)

pip install autobahn[twisted,encryption,serialization,xbr]

or (asyncio, with more bells an whistles)

pip install autobahn[asyncio,encryption,serialization,xbr]

Native vector extensions (NVX)

> This is NOT yet complete - ALPHA!

Autobahn contains NVX, a network accelerator library that provides SIMD accelerated native vector code for WebSocket (XOR masking) and UTF-8 validation.


WAMP Serializers

  • serialization: To install additional WAMP serializers: CBOR, MessagePack, UBJSON and Flatbuffers

Above is for advanced uses. In general we recommend to use CBOR where you can, and JSON (from the standard library) otherwise.


To install Autobahn with all available serializers:

pip install autobahn[serializers]

or (development install)

pip install -e .[serializers]

Further, to speed up JSON on CPython using ujson, set the environment variable:

AUTOBAHN_USE_UJSON=1

Warning

Using ujson (on both CPython and PyPy) will break the ability of Autobahn to transport and translate binary application payloads in WAMP transparently. This ability depends on features of the regular JSON standard library module not available on ujson.

To use cbor2, an alternative, highly flexible and standards complicant CBOR implementation, set the environment variable:

AUTOBAHN_USE_CBOR2=1

Note

cbor2 is not used by default, because it is significantly slower currently in our benchmarking for WAMP message serialization on both CPython and PyPy compared to cbor.

Comments
  • Autobahn shared core API

    Autobahn shared core API

    As we have been discussing various improvements to the AutobahnPython WAMP API like the new Connection class and just using a WAMP Session object instead of being forced to inherit from a Session base class, now is the chance to design a core API for WAMP that is highly similar between:

    • AutobahnPython
    • AutobahnJS
    • AutobahnC
    wamp enhancement needs-discussion 
    opened by oberstet 59
  • Reverse protocol handling for WebSocketResource

    Reverse protocol handling for WebSocketResource

    I have a set of unit tests (in https://github.com/warner/magic-wormhole) that recently started failing when I combine autobahn-0.13.1 and Twisted trunk. It looks like https://github.com/twisted/twisted/commit/4f9e36d8ad21f9d73369f4d506bab30f61c2ad71 (landed 29-Mar-2016) is where the problem started (that's the first revision after Twisted-16.1.1 was branched off that causes my project's tests to fail).

    The commit says:

    Merge hide-request-transport-8191-5: Hide the transport backing the HTTPChannel object from twisted.web Resource objects.
    

    And my tests are using WebSocketResource to put a websocket on a specific URL. I haven't tracked down the specific failure yet, but it seems like the server is having an internal error when the client attempts to connect to it, or the server isn't accepting the connection at all.

    The relevant Twisted bug is at https://twistedmatrix.com/trac/ticket/8191 .

    When I get some time (maybe next week), I'll figure out how to run autobahn's test suite against various versions of Twisted and see what happens.

    websocket wamp bug Twisted 
    opened by warner 55
  • App wrapper on top of ApplicationRunner

    App wrapper on top of ApplicationRunner

    From: https://groups.google.com/forum/#!topic/autobahnws/lmztderi6N4

    What I think is the biggest adoption issue, however, is the API. Autobahn should have a small cost of entry, and right now it doesnt. The hello world is not only hard to write using the documentation, but quite scary :

      from  twisted.python  import  log
      from  twisted.internet.defer  import  inlineCallbacks
    
      from  autobahn.twisted.wamp  import  ApplicationSession
      from  autobahn.twisted.wamp  import  ApplicationRunner
    
    
      class  ListenForEvent(ApplicationSession):
    
    
           def  __init__(self, config):
               ApplicationSession.__init__(self)
               self.config  = config
    
           def  onConnect(self):
               self.join(self.config.realm)
    
    
           @inlineCallbacks
           def  onJoin(self, details):
               callback =lambda  x: log.msg("Received event %s"  %  x)
               yield  self.subscribe(callback,'un_evenement')
    
    
      if  __name__ =='__main__':
          runner = ApplicationRunner(endpoint="tcp:127.0.0.1:8080",
                                     url="ws://localhost:8080/ws",
                                     realm="realm1")
          runner.run(ListenForEvent)
    

    We need a simplified wrapper for that, that can be used for simple use case : small applications, tests, etc. In the same fashion that flask and bottle make web programming much easier than Django. I'm suggesting to add something like this :

      from  autobahn.app  import  App
    
      app = App(url="ws://localhost:8080/ws")
    
      @event("event_name")
      def  handle(details):
           app.log("Received event %s"  %  details)
    
      if  __name__ =='__main__':
          app.run()
    

    Sane defaults, doesn't not cover all the use cases, but it's enought for 80% of the dev. The goal is not to replace the other API, but rather offer something higher level we can show of in the first page of the documentation that would make people started quickly.

    wamp feature 
    opened by oberstet 44
  • Config/Settings to ApplicationRunner (openHandshakeTimeout)

    Config/Settings to ApplicationRunner (openHandshakeTimeout)

    Hi, How can I override default openHandshakeTimeout param? I am going run ApplicationRunner with greater handshake timout in python code. I have tried, but nothing: subscriber = ApplicationRunner(url=u"wss://api.....", realm=u"realm1",extra={'openHandshakeTimeout':10})

    enhancement 
    opened by TonyRehley 35
  • Allow for custom logger to be passed to ApplicationSession

    Allow for custom logger to be passed to ApplicationSession

    ApplicationSession does not currently allow a custom logger to be passed to the logger instance that txaio uses. It would be nice to allow a custom logger to be passed based on the standard lib logging module. This would allow for better control of a log file for administration, and not duplicate entry with no way to stop it:

    [04-28-2016 15:58:32.589 UTC] PID: 1659 Mod: timer Line: 16 INFO: build_json_tree sort finished in: 0.002349 secs
    2016-04-28T11:58:32 build_json_tree sort finished in: 0.002349 secs
    
    class ApplicationSession(BaseSession):
        """
        WAMP endpoint session.
        """
    
        log = txaio.make_logger() or self.config.logger  # NOTE: Or something like this
    
        def __init__(self, config=None):
            """
            Constructor.
            """
            BaseSession.__init__(self)
            self.config = config or types.ComponentConfig(realm=u"default")
    
    class SessionComponent(ApplicationSession):
        def __init__(self, config=None, hostname=None, logger=None):
            ApplicationSession.__init__(self, config, logger)
    
    opened by singlecheeze 27
  • Use batching/chunking timers

    Use batching/chunking timers

    There are multiple places within Autobahn (at the WebSocket and at the WAMP level) where we use timers sticked to protocol instances.

    When running massive numbers of connections, this can lead to significant CPU load.

    Since these timers don't need to be precise, and hence we can conserve CPU by batching timeouts into buckets (and process timeout callbacks within a bucket in chunks).

    The underlying functionality will be in txaio: https://github.com/crossbario/txaio/issues/66

    Once that is done, we should use them here.

    websocket wamp enhancement 
    opened by oberstet 25
  • Updating WebSocket headers on every connection attempt

    Updating WebSocket headers on every connection attempt

    As brought up in #autobahn, currently a WebSocket connection gets its headers from the Factory (via. self.factory.headers). However, a Factory may make many connections and it is desirable to have a hook to change the headers for each connection (for example, when doing re-connections).

    One way would be to mutate the .headers attribute in the Factory. This will "probably" work as there is likely only one "active" protocol instance created per-factory. However, it's not very explicit.

    @exarkun suggested: "maybe something like having WebSocketClientProtocol.onConnect allowed to return a ConnectionRequest (or similar) that can specify headers?

    websocket enhancement needs-discussion 
    opened by meejah 24
  • introduce and encourage use of an interface that is more easily testable

    introduce and encourage use of an interface that is more easily testable

    I've had some difficulty writing good unit tests for WebSocketClientProtocol-based implementations. The tools available seem to encourage one of two paths:

    • Directly instantiate the relevant objects and then call methods on them as though they were in use by the real Autobahn WebSocket implementation.
    • Set up real network servers and clients that interact over real sockets so that the real Autobahn WebSocket implementation is driving them.

    The first of these options has the drawback that there's no guarantee the tests will actually drive the application code correctly (and even if it is initially correct the chances of it diverging from reality increase as Autobahn is maintained and changed).

    The second of these options has the drawback that it is prone to many different kinds of spurious failure (most code that takes this approach doesn't even manage to get the part where you start listening on a port correct :cry: ). It also draws in a lot more code and so failures can become harder to spot. Failures can also end up being caused by other code that's not the main focus of the test. It's also a lot slower/more expensive as a result of running so much more code.

    I think it would be very useful if Autobahn itself offered and encouraged the use of a higher-level interface that allows details about connections/sockets/networks to be contained in an object that can easily be substituted for a testing fake. A model for this which appears to be working well is the regular HTTP client interface in Twisted, twisted.web.client.IAgent. This has one primary network-enabled implementation in Twisted, twisted.web.client.Agent and the third-party(-ish) treq library provides a test-focused implementation, treq.testing.RequestTraversalAgent.

    Application code written against IAgent can accept an implementation and do what it needs to do. Real-world use of this application code passes in an Agent instance (or possibly a wrapper but that's not directly relevant here). Test use of this same application code passes in a correctly initialized RequestTraversalAgent. The application code doesn't know or care which implementation it gets. Agent goes off and makes real requests over a real network. RequestTraversalAgent decomposes the request and serves up a response to it using a twisted.web.resource.IResource provider - with no network, only Python method calls and correct copying of bytes from one place to another in memory.

    enhancement needs-discussion 
    opened by exarkun 23
  • Some files are missing license headers

    Some files are missing license headers

    Hi,

    We're using autobahn in the openstack/zaqar project and we're at the point where we need to start creating packages for it. In order to do so, we also need to create a package for autobahn since it's a dependency. However, debian/ubuntu packagers have raised an issue with regards to some files not having a license. Without this license, it's not possible to package Autobahn.

    The files causing problems are:

    P: python-autobahn source: source-contains-prebuilt-javascript-object examples/twisted/websocket/echo_wsfallbacks/web/swfobject.js mean line length is about 10071 characters
    E: python-autobahn source: source-is-missing examples/twisted/websocket/echo_wsfallbacks/web/swfobject.js
    P: python-autobahn source: source-contains-prebuilt-flash-object examples/twisted/websocket/echo_wsfallbacks/web/WebSocketMain.swf
    E: python-autobahn source: source-is-missing examples/twisted/websocket/echo_wsfallbacks/web/WebSocketMain.swf
    P: python-autobahn source: source-contains-prebuilt-javascript-object examples/twisted/wamp/authentication/ticket/autobahn.min.js
    E: python-autobahn source: source-is-missing examples/twisted/wamp/authentication/ticket/autobahn.min.js
    P: python-autobahn source: source-contains-prebuilt-javascript-object examples/twisted/wamp/authentication/otp/autobahn.min.js
    E: python-autobahn source: source-is-missing examples/twisted/wamp/authentication/otp/autobahn.min.js
    P: python-autobahn source: source-contains-prebuilt-javascript-object examples/twisted/wamp/app/serial2ws/autobahn.min.js
    E: python-autobahn source: source-is-missing examples/twisted/wamp/app/serial2ws/autobahn.min.js
    P: python-autobahn source: source-contains-prebuilt-javascript-object examples/twisted/wamp/app/hello/autobahn.min.js
    E: python-autobahn source: source-is-missing examples/twisted/wamp/app/hello/autobahn.min.js
    
    needs-discussion 
    opened by flaper87 23
  • Insecure masking key selection?

    Insecure masking key selection?

    RFC 6455 says:

    The masking key is a 32-bit value chosen at random by the client. When preparing a masked frame, the client MUST pick a fresh masking key from the set of allowed 32-bit values. The masking key needs to be unpredictable; thus, the masking key MUST be derived from a strong source of entropy, and the masking key for a given frame MUST NOT make it simple for a server/proxy to predict the masking key for a subsequent frame. The unpredictability of the masking key is essential to prevent authors of malicious applications from selecting the bytes that appear on the wire.

    But if I'm reading the code right, autobahn appears to select masks using random.getrandbits, which uses Python's default Mersenne Twister-based RNG. The Mersenne Twister is inappropriate for security-sensitive applications because its future outputs can be predicted by observing previous outputs. (I.e., seeing the first N masks lets you predict the future masks.)

    websocket 
    opened by njsmith 22
  • Asyncio RawSocket

    Asyncio RawSocket

    Hi,

    this is my first attempt for rawsocket transport for aio.

    Few comments for current code:

    • It's python 3 only now - it's bit intentional - since trollius is officially deprecated it does not make much sense for me to support it here - anybody willing to work with asyncio will use python3 anyhow
    • I've tried to make it basically independent on remaining code, self-contained - so basically no changes to other parts of code, that can break something else.
    • This lead to some duplication - mainly in utils module ( which probably should be shared with remaining codebase) and WampRawSocketMixinGeneral in rawsocket module, which contains exactly same code as rawsocket transport for twisted.
    • There is also new runner class ApplicationRunnerRawSocket - again made not to infer with existing code. Potentially it can be easily integrated into current runner - just use additional URI schemes tcp:// and unix:
    • no ssl support yet - I do not need it - main motivation was to has backend asyncio component connected on same computer - so unix socket is what I need.
    • testing - I've written unittests for this addition. Also tested in python 3 against crossbar - example added. Not sure if you have some more advanced tests - quickly looked to testsuite but it looks like tests are mostly focused on websocket.

    Let me know your thoughts - thanks Ivan

    opened by izderadicka 21
  • Adjust CI to deploy wheels to PyPI

    Adjust CI to deploy wheels to PyPI

    In a minimal container I'm building I hit:

    DEPRECATION: autobahn is being installed using the legacy 'setup.py install' method, because it does not have a 'pyproject.toml' and the 'wheel' package is not installed. pip 23.1 will enforce this behaviour change. A possible replacement is to enable the '--use-pep517' option. Discussion can be found at https://github.com/pypa/pip/issues/8559
    

    Can this project be updated to contain a pyproject.toml and have wheels up at https://pypi.org/project/autobahn/#files

    enhancement CI-CD 
    opened by jcpunk 4
  • Undefined behavior for using WAMP features not agreed during feature negotiation

    Undefined behavior for using WAMP features not agreed during feature negotiation

    I have a client talking to a WAMP Basic Profile server (ran by a third party). This doesn't support call cancellation so I think a call made like this:

    # ...
        async def call_endpoint(self, endpoint):
            try:
                resp = await self.call(endpoint, timeout=ENDPOINT_CALL_TIMEOUT_SECONDS * 1000)
            except Exception as e:  # TODO: Tighten this exception
                print(f"Error calling {endpoint}: {e}")
                raise
    

    would ignore the timeout option and carry on running past the timeout?

    I didn't actually notice the timeout option on the call method on my first pass so just wrapped it in asyncio.wait_for with a timeout like this:

    # ...
        async def call_endpoint(self, endpoint):
            try:
                resp = await asyncio.wait_for(self.call(endpoint), timeout=ENDPOINT_CALL_TIMEOUT_SECONDS)
            except (asyncio.TimeoutError) as e:
                print(f"Timeout calling {endpoint}: {e}")
            except Exception as e:  # TODO: Tighten this exception
                print(f"Error calling {endpoint}: {e}")
                raise
    

    But that's throwing the occasional bad_protocol error. I didn't know what the exact issue is but our third party gave me access to the server logs which showed a 49 error code relating to the cancel call and it does always align with being thrown on the call after a 20s timed out call.

    What's the best way to handle timeouts in this situation? I don't want to catch the bad_protocol exception as is in case the client or server changes in a way that this hides another issue. Can I at least see why the bad_protocol exception is being thrown in the exception somehow? I also don't want to allow the client to block indefinitely on the server because we previously saw consistent failures where the client just hangs forever waiting for a response from the server that never arrives.

    Should Autobahn be detecting this lack of support for call cancellation and just silently dropping the task if cancelled in this way? Or throw another exception in some way that can be handled?

    I noticed https://github.com/crossbario/autobahn-python/issues/1127 but while I think there's maybe some similarity in the reply in that issue I don't really see the similarity in the opening post.

    wamp bug needs-discussion 
    opened by tomelliff 9
  • Successful connection doesn't reset the exponential backoff state

    Successful connection doesn't reset the exponential backoff state

    When I kill crossbar, I can see python-autobahn doing exponential backoff which is fine, however, if the connection re-establishes, the existing state isn't cleared. So if there is a subsequent disconnect, instead of the retry_delay being 0, it continues to grow the previous retry delay

    In these circumstances, small outages cause the retry_delay to accumulate, building up to a 5+ minute wait before it even attempts a connection

    I'm looking into how I can reach this from the Component, or if changes need to be made to the library, but I wanted to open this in case anyone has feedback or a workaround

    Thanks in advance

    opened by afk11 2
  • Twisted + websockets + TLS (wss) gives

    Twisted + websockets + TLS (wss) gives "invalid certificate" in Safari (and only there)

    autobahn-python-master/examples/twisted/websocket/echo_tls: I added the Letsencrypt cer&key of the Apache on the server the code is running on; works great in all browsers apart from Safari (no matter if on my macOS with 12.5.1 or on an iPad Air). No chance to find out why.

    autobahn-python-master/examples/twisted/websocket/echo_site_tls: a little bit more information from Safari:

    cer_autobahn

    For reference the same Safari requesting via https from the Apache running with the same certificate on the same machine without any problems:

    cer_apache

    Next experiment: autobahn with asyncio. No sample in github thus I expanded the echo-sample with using a SSL-context to switch to wss:

    SSLcontext = ssl.SSLContext (ssl.PROTOCOL_TLS_SERVER)
    SSLcontext.load_cert_chain ("xxx.cer", "xxx.key")
    ....
    

    which again works great everywhere including Safari.

    The only combination I can not get running is Twisted+Websockets+TLS on Safari. And this is the combination we have written our app with - and I think it isn't a good idea to say "runs everywhere if it's not from Apple". :-) For testing we can go back to http/ws - but that's also not a real "solution".

    Anyone any idea?

    opened by msedv 0
  • E2E Encryption: Publishing to N subscribers

    E2E Encryption: Publishing to N subscribers

    For E2E encryption we need to publish events to multiple subscribers, there may be multiple strategies but the one that I am investigating is to publish N times by using PublishOptions(eligible=recipient_session_id). How the session ID is discovered is a separate thing.

    One thing that is currently missing in autobahn is to have a way to specify which responder_pub to use when an event is being published. Once it supports that, any helper function like publish_bulk(topic, [recipients...]) could be used to achieve the 1:N publishing.

    needs-discussion 
    opened by om26er 11
  • E2E Encryption: Support more keyring strategies

    E2E Encryption: Support more keyring strategies

    We have a platform which runs a WAMP router, that system also has a secure element. each user (mobile phone / website) has their own public/private key generated on login. The current implementation in autobahn ties the Key (mix of originator and responder keys) to a URI.

    This is mostly fine however in our case it is desired to have 1 responder and multiple originators, the originators can dynamically change as people are added/removed from the system.

    From the look of it, it is currently not possible with the autobahn-python API. There are two changes that I think will make the above possible

    1. The Key object should support multiple originators (a list)
    2. the enc_key in the Invocation should be used to determine if the originator is "expected"
    needs-discussion 
    opened by om26er 1
Owner
Crossbar.io
Seamless connectivity for the IoT and real-time microservices
Crossbar.io
Asynchronous HTTP client/server framework for asyncio and Python

Async http client/server framework Key Features Supports both client and server side of HTTP protocol. Supports both client and server Web-Sockets out

aio-libs 13.2k Jan 5, 2023
Python AsyncIO data API to manage billions of resources

Introduction Please read the detailed docs This is the working project of the next generation Guillotina server based on asyncio. Dependencies Python

Plone Foundation 183 Nov 15, 2022
A micro web-framework using asyncio coroutines and chained middleware.

Growler master ' dev Growler is a web framework built atop asyncio, the asynchronous library described in PEP 3156 and added to the standard library i

null 687 Nov 27, 2022
A very simple asynchronous wrapper that allows you to get access to the Oracle database in asyncio programs.

cx_Oracle_async A very simple asynchronous wrapper that allows you to get access to the Oracle database in asyncio programs. Easy to use , buy may not

null 36 Dec 21, 2022
A Python package to easily create APIs in Python.

API_Easy An Python Package for easily create APIs in Python pip install easy-api-builder Requiremnets: <= python 3.6 Required modules --> Flask Docume

Envyre-Coding 2 Jan 4, 2022
The no-nonsense, minimalist REST and app backend framework for Python developers, with a focus on reliability, correctness, and performance at scale.

The Falcon Web Framework Falcon is a reliable, high-performance Python web framework for building large-scale app backends and microservices. It encou

Falconry 9k Jan 1, 2023
The Modern And Developer Centric Python Web Framework. Be sure to read the documentation and join the Slack channel questions: http://slack.masoniteproject.com

NOTE: Masonite 2.3 is no longer compatible with the masonite-cli tool. Please uninstall that by running pip uninstall masonite-cli. If you do not unin

Masonite 1.9k Jan 4, 2023
Free and open source full-stack enterprise framework for agile development of secure database-driven web-based applications, written and programmable in Python.

Readme web2py is a free open source full-stack framework for rapid development of fast, scalable, secure and portable database-driven web-based applic

null 2k Dec 31, 2022
Ape is a framework for Web3 Python applications and smart contracts, with advanced functionality for testing, deployment, and on-chain interactions.

Ape Framework Ape is a framework for Web3 Python applications and smart contracts, with advanced functionality for testing, deployment, and on-chain i

ApeWorX Ltd. 552 Dec 30, 2022
An abstract and extensible framework in python for building client SDKs and CLI tools for a RESTful API.

django-rest-client An abstract and extensible framework in python for building client SDKs and CLI tools for a RESTful API. Suitable for APIs made wit

Certego 4 Aug 25, 2022
Bionic is Python Framework for crafting beautiful, fast user experiences for web and is free and open source

Bionic is fast. It's powered core python without any extra dependencies. Bionic offers stateful hot reload, allowing you to make changes to your code and see the results instantly without restarting your app or losing its state.

 ⚓ 0 Mar 5, 2022
Fast, asynchronous and elegant Python web framework.

Warning: This project is being completely re-written. If you're curious about the progress, reach me on Slack. Vibora is a fast, asynchronous and eleg

vibora.io 5.7k Jan 8, 2023
Screaming-fast Python 3.5+ HTTP toolkit integrated with pipelining HTTP server based on uvloop and picohttpparser.

Japronto! There is no new project development happening at the moment, but it's not abandoned either. Pull requests and new maintainers are welcome. I

Paweł Piotr Przeradowski 8.6k Dec 29, 2022
Tornado is a Python web framework and asynchronous networking library, originally developed at FriendFeed.

Tornado Web Server Tornado is a Python web framework and asynchronous networking library, originally developed at FriendFeed. By using non-blocking ne

null 20.9k Jan 1, 2023
bottle.py is a fast and simple micro-framework for python web-applications.

Bottle: Python Web Framework Bottle is a fast, simple and lightweight WSGI micro web-framework for Python. It is distributed as a single file module a

Bottle Micro Web Framework 7.8k Dec 31, 2022
Sierra is a lightweight Python framework for building and integrating web applications

A lightweight Python framework for building and Integrating Web Applications. Sierra is a Python3 library for building and integrating web applications with HTML and CSS using simple enough syntax. You can develop your web applications with Python, taking advantage of its functionalities and integrating them to the fullest.

null 83 Sep 23, 2022
Flask Sugar is a web framework for building APIs with Flask, Pydantic and Python 3.6+ type hints.

Flask Sugar is a web framework for building APIs with Flask, Pydantic and Python 3.6+ type hints. check parameters and generate API documents automatically. Flask Sugar是一个基于flask,pyddantic,类型注解的API框架, 可以检查参数并自动生成API文档

null 162 Dec 26, 2022
Trame let you weave various components and technologies into a Web Application solely written in Python.

Trame Trame aims to be a framework for building interactive applications using a web front-end in plain Python. Such applications can be used locally

Kitware, Inc. 85 Dec 29, 2022
Fast⚡, simple and light💡weight ASGI micro🔬 web🌏-framework for Python🐍.

NanoASGI Asynchronous Python Web Framework NanoASGI is a fast ⚡ , simple and light ?? weight ASGI micro ?? web ?? -framework for Python ?? . It is dis

Kavindu Santhusa 8 Jun 16, 2022