encode / uvicorn Goto Github PK
View Code? Open in Web Editor NEWAn ASGI web server, for Python. 🦄
Home Page: https://www.uvicorn.org/
License: BSD 3-Clause "New" or "Revised" License
An ASGI web server, for Python. 🦄
Home Page: https://www.uvicorn.org/
License: BSD 3-Clause "New" or "Revised" License
I keep getting those info messages from somewhere. Everything seems to be in order and no zombie processes are left but I'm still wondering why this happens.
Ive been looking at the example app.py that is in the top dir of the source and came across this line
from uvicorn.broadcast import BroadcastMiddleware
which causes an import error. I can not find where BroadcastMiddleware is defined.
Use case: you want to launch an asgi app to a 128 core machine with 128 processes
Problem: 128xprocess boot time takes a while, in dockered environments (like k8s) this becomes an issue, quick boots mean quick deploys
Preload: it takes ~100 times less boot time
Error: RuntimeError: Event loop is closed
Somewhat related: #61
The reason is gunicorn loads the app once and forks from there when preloading, so it seems every fork gets a different loop from the one that preloading got for the asgi app.
Currently responses could come back out of order.
Add sponsor placements
It may be a good idea to establish contribution guidelines for this project in order to help anyone that is interested in improving things but unsure of how to actually engage the process of proposing changes or submitting PRs.
I am a bit unclear on how to approach some of the existing issues, and it would be helpful if there were a process in place to organize/prioritize tasks that need to be done as well as to identify potential blockers.
Perhaps something similar to what Channels does? It seems like a good example of how this could be handled.
Implementation using redis pub/sub.
Interface along these lines:
def ws_connected(message, channels):
channels['reply'].send({'accept': True})
channels['groups'].send({
'group': 'chat',
'add': channels['reply'].name
})
def ws_receive(message, channels):
channels['groups'].send({
'group': 'chat',
'send': message['text']
})
def ws_disconnect(message, channels):
channels['groups'].send({
'group': 'chat',
'discard': channels['reply'].name
})
When a response is sent we should drain any remaining request body.
None of my apistar app's access logging or other logging in application code that works with daphne or gunicorn works here. It seems like logging may not be implemented. Please advise.
Set up ssl context in the worker
Possible that we should also work towards a meinheld based implementation, for existing synchronous frameworks. Needs more thorough thought, investigation.
Expect: 100-Continue
headers gracefully, by only sending if the request body is read prior to sending the response headers.Currently asyncio event loop is replaced in UvicornServer.run
method:
def run(self, app, host, port):
asyncio.get_event_loop().close()
asyncio.set_event_loop_policy(uvloop.EventLoopPolicy())
loop = asyncio.get_event_loop()
Because of that, there is no way for app to do initialization using uvicorn event loop, because before running the server, existing event loop is closed and replaced by new one.
I thin, event loop policy should be change only if uvicorn is the main entry point, for example uvicorn.main.run
could do that. Otherwise, app using uvicorn should take care changing event loop policy.
Support sendfile
usage.
Would require an ASGI extension.
Daphne has config options for websocket timeout
--websocket_timeout WEBSOCKET_TIMEOUT
Maximum time to allow a websocket to be connected. -1
for infinite.
--websocket_connect_timeout WEBSOCKET_CONNECT_TIMEOUT
Maximum time to allow a connection to handshake. -1
for infinite
So server never closes connections by default.
I am trying to use uvicorn to run django asgi with this command.
uvicorn foo.asgi --workers 5 --log-level debug --bind 0.0.0.0:9000 --timeout 14400 --graceful-timeout 14400
Unfortunately, websockets are getting closed after a minute or so. Is there a way to configure this?
In particular sanic & aiohttp
Allow for unsticky websockets, by supporting channel layers.
Hi there,
First of all, congratulations for Uvicorn — it's truly amazing and pleasant to use!
Today I was messing around with Django 2.0 + Channels and thought about giving Uvicorn a try as a replacement for Daphne.
Although everything seems to work like a charm, I see an AttributeError
in my server's log, without this exception surfacing to the browser. It seems to be caused by the following piece of code:
uvicorn/uvicorn/protocols/http.py
Lines 154 to 157 in 24bf63f
Providing some more details below (full traceback + Python package + system details)
Not Found: /favicon.ico
Task exception was never retrieved
future: <Task finished coro=<AsgiHandler.__call__() done, defined at /mnt/data/.python-3.6/lib/python3.6/site-packages/channels/http.py:172> exception=AttributeError("'uvloop.loop.TCPTransport' object has no attribute 'drain'",)>
Traceback (most recent call last):
File "/mnt/data/.python-3.6/lib/python3.6/site-packages/channels/http.py", line 190, in __call__
await self.handle(body)
File "/mnt/data/.python-3.6/lib/python3.6/site-packages/asgiref/sync.py", line 110, in __call__
return await asyncio.wait_for(future, timeout=None)
File "/usr/local/lib/python3.6/asyncio/tasks.py", line 339, in wait_for
return (yield from fut)
File "/usr/local/lib/python3.6/concurrent/futures/thread.py", line 56, in run
result = self.fn(*self.args, **self.kwargs)
File "/mnt/data/.python-3.6/lib/python3.6/site-packages/asgiref/sync.py", line 125, in thread_handler
return self.func(*args, **kwargs)
File "/mnt/data/.python-3.6/lib/python3.6/site-packages/channels/http.py", line 226, in handle
self.send(response_message)
File "/mnt/data/.python-3.6/lib/python3.6/site-packages/asgiref/sync.py", line 64, in __call__
return call_result.result()
File "/usr/local/lib/python3.6/concurrent/futures/_base.py", line 432, in result
return self.__get_result()
File "/usr/local/lib/python3.6/concurrent/futures/_base.py", line 384, in __get_result
raise self._exception
File "/mnt/data/.python-3.6/lib/python3.6/site-packages/asgiref/sync.py", line 78, in main_wrap
result = await self.awaitable(*args, **kwargs)
File "/mnt/data/.python-3.6/lib/python3.6/site-packages/uvicorn/protocols/http.py", line 158, in send
await self.transport.drain()
AttributeError: 'uvloop.loop.TCPTransport' object has no attribute 'drain'
pip freeze
asgiref==2.3.0
async-timeout==2.0.1
attrs==17.4.0
autobahn==18.4.1
Automat==0.6.0
backcall==0.1.0
cffi==1.11.5
channels==2.1.1
constantly==15.1.0
daphne==2.1.1
decorator==4.3.0
dj-database-url==0.5.0
Django==2.0
djangorestframework==3.8.2
gunicorn==19.8.1
httptools==0.0.11
hyperlink==18.0.0
idna==2.6
incremental==17.5.0
ipython==6.3.1
ipython-genutils==0.2.0
jedi==0.12.0
parso==0.2.0
pexpect==4.5.0
pickleshare==0.7.4
prompt-toolkit==1.0.15
psycopg2-binary==2.7.4
ptyprocess==0.5.2
pycparser==2.18
Pygments==2.2.0
pytz==2017.3
sec==0.2.2
simplegeneric==0.8.1
six==1.11.0
traitlets==4.3.2
Twisted==18.4.0
txaio==2.10.0
uvicorn==0.1.1
uvloop==0.9.1
wcwidth==0.1.7
websockets==4.0.1
whitenoise==3.3.1
zope.interface==4.5.0
uvicorn avilpage.asgi --log-level debug --bind 0.0.0.0:8000 --workers 2 --timeout 15
When uvicorn is started with above command, workers doesn't restart after 15 seconds. It doesn't seem to work for t>14
.
For t<=14
, it works.
[2018-06-01 11:16:06 +0530] [9402] [INFO] Booting worker with pid: 9402
[2018-06-01 11:16:06 +0530] [9403] [INFO] Booting worker with pid: 9403
[2018-06-01 11:16:06 +0530] [9385] [DEBUG] 2 workers
[2018-06-01 11:16:20 +0530] [9385] [CRITICAL] WORKER TIMEOUT (pid:9402)
[2018-06-01 11:16:20 +0530] [9385] [CRITICAL] WORKER TIMEOUT (pid:9403)
[2018-06-01 11:16:21 +0530] [9402] [INFO] Error while closing socket [Errno 9] Bad file descriptor
[2018-06-01 11:16:21 +0530] [9402] [INFO] Worker exiting (pid: 9402)
[2018-06-01 11:16:21 +0530] [9403] [INFO] Error while closing socket [Errno 9] Bad file descriptor
[2018-06-01 11:16:21 +0530] [9403] [INFO] Worker exiting (pid: 9403)
[2018-06-01 11:16:21 +0530] [9806] [INFO] Booting worker with pid: 9806
[2018-06-01 11:16:22 +0530] [9385] [DEBUG] 1 workers
[2018-06-01 11:16:22 +0530] [9807] [INFO] Booting worker with pid: 9807
[2018-06-01 11:16:22 +0530] [9385] [DEBUG] 2 workers
uvicorn/__init__.py
has this line:
from uvicorn.run import run
This line shadows uvicorn.run
module and for example, I can't import module like this import uvicorn.run
, because it gives function, not module. But on the other hand, from uvicorn.run import UvicornServer
.
In the worker class
uvicorn==0.1.1
is throwing these errors
uvicorn[7423]: Unhandled exception in event loop
uvicorn[7423]: Traceback (most recent call last):
uvicorn[7423]: File "uvloop/handles/stream.pyx", line 784, in uvloop.loop.__uv_stream_on_read_impl
uvicorn[7423]: File "uvloop/handles/stream.pyx", line 563, in uvloop.loop.UVStream._on_read
uvicorn[7423]: File "/home/web/.virtualenvs/mesh/lib/python3.5/site-packages/uvicorn/protocols/http.py", line 212, in data_received
uvicorn[7423]: self.request_parser.feed_data(data)
uvicorn[7423]: File "httptools/parser/parser.pyx", line 193, in httptools.parser.parser.HttpParser.feed_data
uvicorn[7423]: httptools.parser.errors.HttpParserInvalidMethodError: invalid HTTP method
Eg. support h11, as used in https://github.com/jeamland/guvnor/blob/master/guvnor/asyncio_worker.py
In particular it'd be good to have a pure-python configuration available to us.
If anyone's interested in helping move this forward I'd suggest that a good first approach would be a pull request that removes http_parser, and replaces it with h11. That'll then help us figure out where their interfaces are different, and help us work towards what we'd like the generalized interface to be.
/cc @jeamland
Hi folks, have you benchmarked this on PyPy? Just curious as to whether using the standard asyncio implementation under PyPy would be faster than uvloop due to thunking across the Cython FFI.
We've temporarily dropped pipelining support from the httptools
implementation, although everythings in place in order to support it. Need to:
Keep track of queued request/response cycles if a new cycle starts before the existing one has finished. Callback to the protocol to start the next cycle in the queue if needed.
Using the h2 package.
Can uvicorn support windows?
I am develops in windows, and want to use uvicorn.
When running applications like uvicorn behind a reverse proxy like NGINX it is best practice to use a unix domain socket instead of binding to an ip address. This has the benefit of improved security and performance.
This could be implemented the same way as gunicorn does it. If the bind parameter starts with unix:
, use a unix domain socket. One caveat is that the socket file will have to be created beforehand and cleaned up afterwards.
Given that the raison d'être of asyncio is achieving high concurrency, we should get TechEmpower benchmarks for the most realistic test types (eg. fortune)
First frame of any body data could fill 'body' rather than create a body queue.
This'd be nicer for debugging incoming request messages, as some or all of the body data will be visible in the http.request
message.
I encountered the following exception while running an apistar application using uvicorn 0.0.15 on CPython 3.6.4 with SSL enabled:
Unhandled exception in event loop
Traceback (most recent call last):
File "httptools/parser/parser.pyx", line 241, in httptools.parser.parser.cb_on_url
File "/home/omer/.local/share/virtualenvs/myproject--RkZn49j/lib/python3.6/site-packages/uvicorn/protocols/http.py", line 278, in on_url
'path': parsed.path.decode('ascii'),
AttributeError: 'NoneType' object has no attribute 'decode'
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "uvloop/handles/stream.pyx", line 784, in uvloop.loop.__uv_stream_on_read_impl
File "uvloop/handles/stream.pyx", line 563, in uvloop.loop.UVStream._on_read
File "/home/omer/.pyenv/versions/3.6.4/lib/python3.6/asyncio/sslproto.py", line 514, in data_received
self._app_protocol.data_received(chunk)
File "/home/omer/.local/share/virtualenvs/myproject--RkZn49j/lib/python3.6/site-packages/uvicorn/protocols/http.py", line 238, in data_received
self.request_parser.feed_data(data)
File "httptools/parser/parser.pyx", line 189, in httptools.parser.parser.HttpParser.feed_data
httptools.parser.errors.HttpParserCallbackError: the on_url callback failed
The exception occurs when the empty HTTP message b' HTTP/1.1\r\n'
is provided in https://github.com/encode/uvicorn/blob/master/uvicorn/protocols/http.py#L238
Unfortunately I'm unable to reproduce this problem with requests or curl.
So far the only HTTP client that reproduces this bug is OSQuery 2.11.2 with the remote API enabled. OSQuery 2.8.0 does not present the same problem.
I'm running uvicorn with the following parameters:
uvicorn myproject.app:app \
--workers=8 \
--bind=localhost:8080 \
--keyfile=./server.pem \
--certfile=./server.pem \
--ca-certs=./ca.pem \
--log-level DEBUG \
--access-logfile=- \
--do-handshake-on-connect \
--ciphers TLSv1.2
and OSQuery with the following parameters:
sudo osqueryd --pidfile /tmp/osqueryd.pid --verbose --debug \
--database_path /tmp/osquery.db/ \
--tls_hostname localhost:8080 \
--config_plugin tls \
--tls_server_certs /usr/local/share/ca-certificates/ca.crt \
--config_tls_endpoint /collection/configuration \
--logger_tls_endpoint /collection/log_event \
--logger_plugin tls \
--enroll_tls_endpoint /collection/enroll \
--disable_distributed=false --distributed_plugin=tls --distributed_interval=60 \
--distributed_tls_read_endpoint /collection/queries \
--distributed_tls_write_endpoint /collection/results \
--watchdog_level -1 \
--enroll_secret_path ./etc/test_enroll_secret.txt
In order to reproduce the problem you'll need to generate your own certificates.
I recommend trustme for that purpose.
I'm going to try to reverse proxy with Nginx next to figure out if OSQuery is at fault here but in any case, the uvicorn should handle malformed (or incomplete? not sure about that) HTTP requests more gracefully.
If application responds with a connection: close header then the transport should be closed.
Once the h11 integration is complete we could add uvicorn to the zenchmarks, which I'm guessing might get re-run when pypy3 gets an official release.
https://github.com/squeaky-pl/zenchmarks
Worth re-iterating that the pure-python version still looks significantly slower than the c-implementation, but a worthwhile aim all the same.
Hi,
I was trying to run this example using uvicorn + websockets 4.0.1 (latest version):
async def chat_server(message, channels):
"""
ASGI-style 'Hello, world' application.
"""
if message['channel'] == 'websocket.connect':
await channels['reply'].send({'accept': True})
And I get this error after sending the accept message.
Starting worker [9001] serving at: 0.0.0.0:8000
Task exception was never retrieved
future: <Task finished coro=<reader() done, defined at /home/vinicius/projects/dealer/venv/lib/python3.6/site-packages/uvicorn/protocols/websocket.py:65> exception=TypeError('An asyncio.Future, a coroutine or an awaitable is required',)>
Traceback (most recent call last):
File "/home/vinicius/projects/dealer/venv/lib/python3.6/site-packages/uvicorn/protocols/websocket.py", line 72, in reader
data = await protocol.recv()
File "/home/vinicius/projects/dealer/venv/lib/python3.6/site-packages/websockets/protocol.py", line 309, in recv
loop=self.loop, return_when=asyncio.FIRST_COMPLETED)
File "/usr/lib/python3.6/asyncio/tasks.py", line 311, in wait
fs = {ensure_future(f, loop=loop) for f in set(fs)}
File "/usr/lib/python3.6/asyncio/tasks.py", line 311, in <setcomp>
fs = {ensure_future(f, loop=loop) for f in set(fs)}
File "/usr/lib/python3.6/asyncio/tasks.py", line 526, in ensure_future
raise TypeError('An asyncio.Future, a coroutine or an awaitable is '
TypeError: An asyncio.Future, a coroutine or an awaitable is required
It works fine with websockets 3.4.0
I was looking into it and I noticed that in the protocol.py (from websockets) the variable transfer_data_task
is not initialized so a None
is being added to the queue of events causing the error.
It could be a bug in websockets 4.0.* or they have changed the logic and uvicorn is not compatible anymore.
send()
should just be a plain function, buffers the output? No: server should handle calling await transport.drain()
when required..channels = [...]
attribute on the consumer callable.exc_info
? Using cached https://files.pythonhosted.org/packages/c7/a7/92333ff7e11f703af974485247ae1231bed96d3e9b8e5a48f4009d985761/uvicorn-0.2.0.tar.gz
Complete output from command python setup.py egg_info:
Traceback (most recent call last):
File "<string>", line 1, in <module>
File "/private/var/folders/4g/1rsbx7zd74z2pz2x_qhbhwlm0004z1/T/pip-install-92dplo46/uvicorn/setup.py", line 44, in <module>
long_description=get_long_description(),
File "/private/var/folders/4g/1rsbx7zd74z2pz2x_qhbhwlm0004z1/T/pip-install-92dplo46/uvicorn/setup.py", line 23, in get_long_description
return open('README.md', 'r').read()
FileNotFoundError: [Errno 2] No such file or directory: 'README.md'
I believe, include those to MANIFEST could help (not sure, I always had troubles with python packaging)
Responses need to support Transfer-Encoding: Chunked
def on_body(self, body: bytes):
if self.body:
self.parsing_request.put_message({
'type': 'http.request',
'body': self.body,
'more_body': True
})
self.check_pause_reading()
self.body = body
because of this method, when upload a file bigger than 1M, method check_pause_reading
will block
with self.read_paused set to True。
Uvicorn sometimes throws this error when client tries to disconnect. This doesn't seem to happen when daphne is used.
Task exception was never retrieved
future: <Task finished coro=<websocket_session() done, defined at /home/chillar/.virtualenvs/mesh/lib/python3.6/site-packages/uvicorn/protocols/websocket.py:31> exception=TypeError("'<=' not supported between instances of 'int' and 'NoneType'",)>
Traceback (most recent call last):
File "/home/chillar/.virtualenvs/mesh/lib/python3.6/site-packages/uvicorn/protocols/websocket.py", line 40, in websocket_session
data = await protocol.recv()
File "/home/chillar/.virtualenvs/avilpage.com/lib/python3.6/site-packages/websockets/protocol.py", line 323, in recv
raise ConnectionClosed(self.close_code, self.close_reason)
File "/home/chillar/.virtualenvs/avilpage.com/lib/python3.6/site-packages/websockets/exceptions.py", line 147, in __init__
if 3000 <= code < 4000:
TypeError: '<=' not supported between instances of 'int' and 'NoneType'
I think that the process for accept and close keys in ReplyChannel.send() of WebSocket is necessary.
We should expose a plain python .serve(host, port)
style interface, for when you don't want fully-fledged gunicorn process management.
Is this software compatible with sanic, or does sanic need asgi interface to work with this?
The httptools
implementation (default) supports websockets upgrades, but the h11
implementation doesn't yet.
Add this support, and then ensure that the websocket tests run against both protocol classes.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.