Skip to main content

WSGI server implemented in Rust.

Project description

Pyruvate WSGI server

https://gitlab.com/tschorr/pyruvate/badges/main/pipeline.svg https://codecov.io/gl/tschorr/pyruvate/branch/main/graph/badge.svg http://img.shields.io/pypi/v/pyruvate.svg

Pyruvate is a fast, multithreaded WSGI server implemented in Rust.

Features

Installation

If you are on Linux and use a recent Python version,

$ pip install pyruvate

is probably all you need to do.

Binary Packages

manylinux_2_17 and musllinux_1_1 wheels are available for the x86_64 architecture and active Python 3 versions (currently 3.7-3.11).

Source Installation

On macOS or if for any other reason you want to install the source tarball (e.g. using pip install –no-binary) you will need to install Rust first.

Development Installation

  • Install Rust

  • Install and activate a Python 3 (>= 3.7) virtualenv

  • Install setuptools_rust using pip:

    $ pip install setuptools_rust
  • Install Pyruvate, e.g. using pip:

    $ pip install -e git+https://gitlab.com/tschorr/pyruvate.git#egg=pyruvate[test]

Using Pyruvate in your WSGI application

From Python

A hello world WSGI application using Pyruvate listening on 127.0.0.1:7878 and using 2 worker threads looks like this:

import pyruvate

def application(environ, start_response):
    """Simplest possible application object"""
    status = '200 OK'
    response_headers = [('Content-type', 'text/plain')]
    start_response(status, response_headers, None)
    return [b"Hello world!\n"]

pyruvate.serve(application, "127.0.0.1:7878", 2)

Using PasteDeploy

Again listening on 127.0.0.1:7878 and using 2 worker threads:

[server:main]
use = egg:pyruvate#main
socket = 127.0.0.1:7878
workers = 2

Configuration Options

socket

Required: The TCP socket Pyruvate should bind to. Pyruvate also supports systemd socket activation If you specify None as the socket value, Pyruvate will try to acquire a socket bound by systemd.

workers

Required: Number of worker threads to use.

async_logging

Optional: Log asynchronously using a dedicated thread. Defaults to True.

chunked_transfer

Optional: Whether to use chunked transfer encoding if no Content-Length header is present. Defaults to False.

keepalive_timeout

Optional: Specify a timeout in integer seconds for keepalive connection. The persistent connection will be closed after the timeout expires. Defaults to 60 seconds.

max_number_headers

Optional: Maximum number of request headers that will be parsed. If a request contains more headers than configured, request processing will stop with an error indicating an incomplete request. The default is 32 headers

max_reuse_count

Optional: Specify how often to reuse an existing connection. Setting this parameter to 0 will effectively disable keep-alive connections. This is the default.

qmon_warn_threshold

Optional: Warning threshold for the number of requests in the request queue. A warning will be logged if the number of queued requests reaches this value. The value must be a positive integer. The default is None which disables the queue monitor.

send_timeout

Optional: Time to wait for a client connection to become available for writing after EAGAIN, in seconds. Connections that do not receive data within this time are closed. The value must be a positive integer. The default is 60 seconds.

Logging

Pyruvate uses the standard Python logging facility. The logger name is pyruvate. See the Python documentation (logging, logging.config) for configuration options.

Example Configurations

Django

After installing Pyruvate in your Django virtualenv, create or modify your wsgi.py file (one worker listening on 127.0.0.1:8000):

import os
import pyruvate

from django.core.wsgi import get_wsgi_application

os.environ.setdefault("DJANGO_SETTINGS_MODULE", "your_django_application.settings")

application = get_wsgi_application()

pyruvate.serve(application, "127.0.0.1:8000", 1)

You can now start Django + Pyruvate with:

$ python wsgi.py

Override settings by using the DJANGO_SETTINGS_MODULE environment variable when appropriate. Tested with Django 4.1.x, 3.2.x, 2.2.x.

MapProxy

First create a basic WSGI configuration following the MapProxy deployment documentation. Then modify config.py so it is using Pyruvate (2 workers listening on 127.0.0.1:8005):

import os.path
import pyruvate

from mapproxy.wsgiapp import make_wsgi_app
application = make_wsgi_app(r'/path/to/mapproxy/mapproxy.yaml')

pyruvate.serve(application, "127.0.0.1:8005", 2)

Start from your virtualenv:

$ python config.py

Tested with Mapproxy 1.15.x, 1.13.x, 1.12.x.

Plone

Using pip

After installing Pyruvate in your Plone virtualenv, change the server section in your zope.ini file (located in instance/etc if you are using mkwsgiinstance to create the instance):

[server:main]
use = egg:pyruvate#main
socket = localhost:7878
workers = 2
Using zc.buildout

Using zc.buildout and plone.recipe.zope2instance you can define an instance part using Pyruvate’s PasteDeploy entry point:

[instance]
recipe = plone.recipe.zope2instance
http-address = 127.0.0.1:8080
eggs =
    Plone
    pyruvate
wsgi-ini-template = ${buildout:directory}/templates/pyruvate.ini.in

The server section of the template provided with the wsgi-ini-template option should look like this (3 workers listening on http-address as specified in the buildout [instance] part):

[server:main]
use = egg:pyruvate#main
socket = %(http_address)s
workers = 3

There is a minimal buildout example configuration for Plone 5.2 in the examples directory of the package.

Tested with Plone 6.0.x, 5.2.x.

Pyramid

Install Pyruvate in your Pyramid virtualenv using pip:

$ pip install pyruvate

Modify the server section in your .ini file to use Pyruvate’s PasteDeploy entry point (listening on 127.0.0.1:7878 and using 5 workers):

[server:main]
use = egg:pyruvate#main
socket = 127.0.0.1:7878
workers = 5

Start your application as usual using pserve:

$ pserve path/to/your/configfile.ini

Tested with Pyramid 2.0, 1.10.x.

Radicale

You can find an example configuration for Radicale in the examples directory of the package. Tested with Radicale 3.1.8.

Nginx settings

Like other WSGI servers Pyruvate should be used behind a reverse proxy, e.g. Nginx:

....
location / {
    proxy_pass http://localhost:7878;
    ...
}
...

Nginx doesn’t use keepalive connections by default so you will need to modify your configuration if you want persistent connections.

Changelog

1.2.1 (2022-12-22)

  • Track and remove unfinished responses that did not otherwise error (#23)

  • Build musllinux_1_1 wheels (#24)

1.2.0 (2022-10-26)

  • Support Python 3.11 and discontinue Python 3.6, switch to manylinux2014 for building wheels (#19)

  • Add a request queue monitor (#17)

  • Remove blocking worker (#18)

  • Improve parsing of Content-Length header (#20)

1.1.4 (2022-04-19)

  • Fix handling of empty list responses (#14)

  • Support hostnames in socket addresses (#15)

1.1.3 (2022-04-11)

  • Simplify response writing and improve performance (#12)

  • Improve signal handling (#13)

1.1.2 (2022-01-10)

  • Migrate to Rust 2021

  • Use codecov binary uploader

  • Add CONTRIBUTING.rst

  • Fixed: The wrk benchmarking tool could make pyruvate hang when there is no Content-Length header (#11)

1.1.1 (2021-10-12)

  • Support Python 3.10

1.1.0 (2021-09-14)

  • Refactor FileWrapper and improve its performance

  • Increase the default maximum number of headers

  • Add Radicale example configuration

  • Update development status

1.0.3 (2021-06-05)

  • HEAD request: Do not complain about content length mismatch (#4)

  • More appropriate log level for client side connection termination (#5)

  • Simplify request parsing

1.0.2 (2021-05-02)

  • Close connection and log an error in the case where the actual content length is less than the Content-Length header provided by the application

  • Fix readme

1.0.1 (2021-04-28)

  • Fix decoding of URLs that contain non-ascii characters

  • Raise Python exception when response contains objects other than bytestrings instead of simply logging the error.

1.0.0 (2021-03-24)

  • Improve query string handling

0.9.2 (2021-01-30)

  • Better support for HTTP 1.1 Expect/Continue

  • Improve documentation

0.9.1 (2021-01-13)

  • Improve GIL handling

  • Propagate worker thread name to Python logging

  • Do not report broken pipe as error

  • PasteDeploy entry point: fix option handling

0.9.0 (2021-01-06)

  • Reusable connections

  • Chunked transfer-encoding

  • Support macOS

0.8.4 (2020-12-12)

  • Lower CPU usage

0.8.3 (2020-11-26)

  • Clean wheel build directories

  • Fix some test isolation problems

  • Remove a println

0.8.2 (2020-11-17)

  • Fix blocksize handling for sendfile case

  • Format unix stream peer address

  • Use latest mio

0.8.1 (2020-11-10)

  • Receiver in non-blocking worker must not block when channel is empty

0.8.0 (2020-11-07)

  • Logging overhaul

  • New async_logging option

  • Some performance improvements

  • Support Python 3.9

  • Switch to manylinux2010 platform tag

0.7.1 (2020-09-16)

  • Raise Python exception when socket is unavailable

  • Add Pyramid configuration example in readme

0.7.0 (2020-08-30)

  • Use Python logging

  • Display server info on startup

  • Fix socket activation for unix domain sockets

0.6.2 (2020-08-12)

  • Improved logging

  • PasteDeploy entry point now also uses at most 24 headers by default

0.6.1 (2020-08-10)

  • Improve request parsing

  • Increase default maximum number of headers to 24

0.6.0 (2020-07-29)

  • Support unix domain sockets

  • Improve sendfile usage

0.5.3 (2020-07-15)

  • Fix testing for completed sendfile call in case of EAGAIN

0.5.2 (2020-07-15)

  • Fix testing for completed response in case of EAGAIN

  • Cargo update

0.5.1 (2020-07-07)

  • Fix handling of read events

  • Fix changelog

  • Cargo update

  • ‘Interrupted’ error is not a todo

  • Remove unused code

0.5.0 (2020-06-07)

  • Add support for systemd socket activation

0.4.0 (2020-06-29)

  • Add a new worker that does nonblocking write

  • Add default arguments

  • Add option to configure maximum number of request headers

  • Add Via header

0.3.0 (2020-06-16)

  • Switch to rust-cpython

  • Fix passing of tcp connections to worker threads

0.2.0 (2020-03-10)

  • Added some Python tests (using py.test and tox)

  • Improve handling of HTTP headers

  • Respect content length header when using sendfile

0.1.0 (2020-02-10)

  • Initial release

Project details


Release history Release notifications | RSS feed

Download files

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

Source Distribution

pyruvate-1.2.1.tar.gz (57.9 kB view details)

Uploaded Source

Built Distributions

pyruvate-1.2.1-cp311-cp311-musllinux_1_1_x86_64.whl (1.3 MB view details)

Uploaded CPython 3.11 musllinux: musl 1.1+ x86-64

pyruvate-1.2.1-cp311-cp311-manylinux_2_17_x86_64.whl (1.3 MB view details)

Uploaded CPython 3.11 manylinux: glibc 2.17+ x86-64

pyruvate-1.2.1-cp310-cp310-musllinux_1_1_x86_64.whl (1.3 MB view details)

Uploaded CPython 3.10 musllinux: musl 1.1+ x86-64

pyruvate-1.2.1-cp310-cp310-manylinux_2_17_x86_64.whl (1.3 MB view details)

Uploaded CPython 3.10 manylinux: glibc 2.17+ x86-64

pyruvate-1.2.1-cp39-cp39-musllinux_1_1_x86_64.whl (1.3 MB view details)

Uploaded CPython 3.9 musllinux: musl 1.1+ x86-64

pyruvate-1.2.1-cp39-cp39-manylinux_2_17_x86_64.whl (1.3 MB view details)

Uploaded CPython 3.9 manylinux: glibc 2.17+ x86-64

pyruvate-1.2.1-cp38-cp38-musllinux_1_1_x86_64.whl (1.3 MB view details)

Uploaded CPython 3.8 musllinux: musl 1.1+ x86-64

pyruvate-1.2.1-cp38-cp38-manylinux_2_17_x86_64.whl (1.3 MB view details)

Uploaded CPython 3.8 manylinux: glibc 2.17+ x86-64

pyruvate-1.2.1-cp37-cp37m-musllinux_1_1_x86_64.whl (1.3 MB view details)

Uploaded CPython 3.7m musllinux: musl 1.1+ x86-64

pyruvate-1.2.1-cp37-cp37m-manylinux_2_17_x86_64.whl (1.3 MB view details)

Uploaded CPython 3.7m manylinux: glibc 2.17+ x86-64

File details

Details for the file pyruvate-1.2.1.tar.gz.

File metadata

  • Download URL: pyruvate-1.2.1.tar.gz
  • Upload date:
  • Size: 57.9 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/3.4.2 importlib_metadata/4.8.1 pkginfo/1.7.1 requests/2.26.0 requests-toolbelt/0.9.1 tqdm/4.62.3 CPython/3.10.0

File hashes

Hashes for pyruvate-1.2.1.tar.gz
Algorithm Hash digest
SHA256 72df10e27efca0b5a16049639629744afdb505960a7d88016c6440cb394b9b12
MD5 1551b344143b4d9229f80e7830a4a6eb
BLAKE2b-256 081bbb830b74aee69d29f01458cf7203aa8824306ca0ebcaba3862d8fdfad133

See more details on using hashes here.

File details

Details for the file pyruvate-1.2.1-cp311-cp311-musllinux_1_1_x86_64.whl.

File metadata

  • Download URL: pyruvate-1.2.1-cp311-cp311-musllinux_1_1_x86_64.whl
  • Upload date:
  • Size: 1.3 MB
  • Tags: CPython 3.11, musllinux: musl 1.1+ x86-64
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/3.4.2 importlib_metadata/4.8.1 pkginfo/1.7.1 requests/2.26.0 requests-toolbelt/0.9.1 tqdm/4.62.3 CPython/3.10.0

File hashes

Hashes for pyruvate-1.2.1-cp311-cp311-musllinux_1_1_x86_64.whl
Algorithm Hash digest
SHA256 e956dc9361b28217eeac3edccba0b234c3cfbe3982ba229d3b118d7bb562cc96
MD5 7b5c12fd83ce5482bd54ae5c1f732752
BLAKE2b-256 6d0eccf73a9ec2fb14e535af853df1a845fa9cdf8e54342b414b7e6097923631

See more details on using hashes here.

File details

Details for the file pyruvate-1.2.1-cp311-cp311-manylinux_2_17_x86_64.whl.

File metadata

  • Download URL: pyruvate-1.2.1-cp311-cp311-manylinux_2_17_x86_64.whl
  • Upload date:
  • Size: 1.3 MB
  • Tags: CPython 3.11, manylinux: glibc 2.17+ x86-64
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/3.4.2 importlib_metadata/4.8.1 pkginfo/1.7.1 requests/2.26.0 requests-toolbelt/0.9.1 tqdm/4.62.3 CPython/3.10.0

File hashes

Hashes for pyruvate-1.2.1-cp311-cp311-manylinux_2_17_x86_64.whl
Algorithm Hash digest
SHA256 eabd22e9a425e7270c1123cb0d3ced4f71a2d9f3ca453150ad095f14f6e17cd2
MD5 091adb352e3f865303c9c3883434311c
BLAKE2b-256 391a2cf5c065f83c3136f1286abfb9135a8847700cea1f44c5358e233b514998

See more details on using hashes here.

File details

Details for the file pyruvate-1.2.1-cp310-cp310-musllinux_1_1_x86_64.whl.

File metadata

  • Download URL: pyruvate-1.2.1-cp310-cp310-musllinux_1_1_x86_64.whl
  • Upload date:
  • Size: 1.3 MB
  • Tags: CPython 3.10, musllinux: musl 1.1+ x86-64
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/3.4.2 importlib_metadata/4.8.1 pkginfo/1.7.1 requests/2.26.0 requests-toolbelt/0.9.1 tqdm/4.62.3 CPython/3.10.0

File hashes

Hashes for pyruvate-1.2.1-cp310-cp310-musllinux_1_1_x86_64.whl
Algorithm Hash digest
SHA256 98ade3ec91ba0e39231eab43cbd67d0012e77e61582e97417eb58f36eee1e6ee
MD5 67b21381bc460d27381ce6d7c065301c
BLAKE2b-256 58a4fcb2741b28e793839e665c8db9e0ac69ad9b886489462f004ac463b068c4

See more details on using hashes here.

File details

Details for the file pyruvate-1.2.1-cp310-cp310-manylinux_2_17_x86_64.whl.

File metadata

  • Download URL: pyruvate-1.2.1-cp310-cp310-manylinux_2_17_x86_64.whl
  • Upload date:
  • Size: 1.3 MB
  • Tags: CPython 3.10, manylinux: glibc 2.17+ x86-64
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/3.4.2 importlib_metadata/4.8.1 pkginfo/1.7.1 requests/2.26.0 requests-toolbelt/0.9.1 tqdm/4.62.3 CPython/3.10.0

File hashes

Hashes for pyruvate-1.2.1-cp310-cp310-manylinux_2_17_x86_64.whl
Algorithm Hash digest
SHA256 c626dd418eaa6d0eb8e238844e169a12e13e0494c8511a01160ce8fa43ad6b2e
MD5 66b8f5f6a9e14a9ca31948bd871b1e0c
BLAKE2b-256 6d053f2750381de1b5a7de92b57029e86ee9b2c461963b578ec9eb22e2ad1905

See more details on using hashes here.

File details

Details for the file pyruvate-1.2.1-cp39-cp39-musllinux_1_1_x86_64.whl.

File metadata

  • Download URL: pyruvate-1.2.1-cp39-cp39-musllinux_1_1_x86_64.whl
  • Upload date:
  • Size: 1.3 MB
  • Tags: CPython 3.9, musllinux: musl 1.1+ x86-64
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/3.4.2 importlib_metadata/4.8.1 pkginfo/1.7.1 requests/2.26.0 requests-toolbelt/0.9.1 tqdm/4.62.3 CPython/3.10.0

File hashes

Hashes for pyruvate-1.2.1-cp39-cp39-musllinux_1_1_x86_64.whl
Algorithm Hash digest
SHA256 a01a56e54e64209e9c72547b1061a2f814953679acf47ffcad80c541b6dda396
MD5 bdfc0d3ec2b7262c335f6276f2dde42f
BLAKE2b-256 c6035d9c21b10c5b8f6d8fd0eed8f5346077cade16f9cda620d06b303b227260

See more details on using hashes here.

File details

Details for the file pyruvate-1.2.1-cp39-cp39-manylinux_2_17_x86_64.whl.

File metadata

  • Download URL: pyruvate-1.2.1-cp39-cp39-manylinux_2_17_x86_64.whl
  • Upload date:
  • Size: 1.3 MB
  • Tags: CPython 3.9, manylinux: glibc 2.17+ x86-64
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/3.4.2 importlib_metadata/4.8.1 pkginfo/1.7.1 requests/2.26.0 requests-toolbelt/0.9.1 tqdm/4.62.3 CPython/3.10.0

File hashes

Hashes for pyruvate-1.2.1-cp39-cp39-manylinux_2_17_x86_64.whl
Algorithm Hash digest
SHA256 9aa1720263e754be1e76d77261c38d351b8fcdecfe330e1dd6fdcd2b92404087
MD5 78177b2fa22ea6a8c6991b3e1b8994d0
BLAKE2b-256 7af67ce261e018611d7d222b299254a1952ccaa395e36a0e5174357603a3d737

See more details on using hashes here.

File details

Details for the file pyruvate-1.2.1-cp38-cp38-musllinux_1_1_x86_64.whl.

File metadata

  • Download URL: pyruvate-1.2.1-cp38-cp38-musllinux_1_1_x86_64.whl
  • Upload date:
  • Size: 1.3 MB
  • Tags: CPython 3.8, musllinux: musl 1.1+ x86-64
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/3.4.2 importlib_metadata/4.8.1 pkginfo/1.7.1 requests/2.26.0 requests-toolbelt/0.9.1 tqdm/4.62.3 CPython/3.10.0

File hashes

Hashes for pyruvate-1.2.1-cp38-cp38-musllinux_1_1_x86_64.whl
Algorithm Hash digest
SHA256 a582925d53ed0da9f4e4de546bc08c3fe6de1fe5b38323700b28179fe0f1a481
MD5 ca0f549ec7ac7ee39b1e6bb138c91f49
BLAKE2b-256 629dbb8e040906dcbba4d3450643f8c8ceda724d71c12b7481b3f1296a19be6a

See more details on using hashes here.

File details

Details for the file pyruvate-1.2.1-cp38-cp38-manylinux_2_17_x86_64.whl.

File metadata

  • Download URL: pyruvate-1.2.1-cp38-cp38-manylinux_2_17_x86_64.whl
  • Upload date:
  • Size: 1.3 MB
  • Tags: CPython 3.8, manylinux: glibc 2.17+ x86-64
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/3.4.2 importlib_metadata/4.8.1 pkginfo/1.7.1 requests/2.26.0 requests-toolbelt/0.9.1 tqdm/4.62.3 CPython/3.10.0

File hashes

Hashes for pyruvate-1.2.1-cp38-cp38-manylinux_2_17_x86_64.whl
Algorithm Hash digest
SHA256 2c60226f04b6eaedb97aedc8917b5c646c4b82fad992e1d2eafbbdf172010c1e
MD5 852bc757af672a45a2674b34846343df
BLAKE2b-256 acbc1807e81dbaf2e864142206030fe3998ed83402d3fd72a5926450748aa84d

See more details on using hashes here.

File details

Details for the file pyruvate-1.2.1-cp37-cp37m-musllinux_1_1_x86_64.whl.

File metadata

  • Download URL: pyruvate-1.2.1-cp37-cp37m-musllinux_1_1_x86_64.whl
  • Upload date:
  • Size: 1.3 MB
  • Tags: CPython 3.7m, musllinux: musl 1.1+ x86-64
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/3.4.2 importlib_metadata/4.8.1 pkginfo/1.7.1 requests/2.26.0 requests-toolbelt/0.9.1 tqdm/4.62.3 CPython/3.10.0

File hashes

Hashes for pyruvate-1.2.1-cp37-cp37m-musllinux_1_1_x86_64.whl
Algorithm Hash digest
SHA256 3b9640c378e868c35e8d44c6136a36a9e6afc7c673570ec11fdd691928b6f3eb
MD5 9d0b58016090e5733548732148e5aa59
BLAKE2b-256 fbde30c56473bbeb1cb2f7f95e68c875362b9eb3a71193fe668eef24b706136e

See more details on using hashes here.

File details

Details for the file pyruvate-1.2.1-cp37-cp37m-manylinux_2_17_x86_64.whl.

File metadata

  • Download URL: pyruvate-1.2.1-cp37-cp37m-manylinux_2_17_x86_64.whl
  • Upload date:
  • Size: 1.3 MB
  • Tags: CPython 3.7m, manylinux: glibc 2.17+ x86-64
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/3.4.2 importlib_metadata/4.8.1 pkginfo/1.7.1 requests/2.26.0 requests-toolbelt/0.9.1 tqdm/4.62.3 CPython/3.10.0

File hashes

Hashes for pyruvate-1.2.1-cp37-cp37m-manylinux_2_17_x86_64.whl
Algorithm Hash digest
SHA256 7a30083a755d73c404e5ffa879cef86ad7b73ba936e8d969f7a733029d133f9d
MD5 5777c34405833941942c56f47a83b18f
BLAKE2b-256 881b0f3df644126f454e85b62eedfb5c9753ef5cfb04e41d81a35d72e03d9c2e

See more details on using hashes here.

Supported by

AWS AWS Cloud computing and Security Sponsor Datadog Datadog Monitoring Fastly Fastly CDN Google Google Download Analytics Microsoft Microsoft PSF Sponsor Pingdom Pingdom Monitoring Sentry Sentry Error logging StatusPage StatusPage Status page