sanic-org / sanic Goto Github PK
View Code? Open in Web Editor NEWAccelerate your web app development | Build fast. Run fast.
Home Page: https://sanic.dev
License: MIT License
Accelerate your web app development | Build fast. Run fast.
Home Page: https://sanic.dev
License: MIT License
Just wanted to comment on this because I wanted to contribute some documentation for sanic, but I just wanted to let you know all of your indentation right now is being done with tabs.
Instead of submitting a pull request for this though, and overwriting all the hard work you did to get this up and running, I thought I would submit an issue to allow you to fix it yourself.
It's as easy as running :retab
in vim or if you are using pycharm it's as easy as reformatting.
Or you could use something like sed.
I can still take care of it if you want just let me know.
Maybe we should add a simple benchmark to make sure that any changes added won't mess with the performance so that every pull request gets run against the same benchmark.
I think it's a little long-winded.
in sanic:
@app.route("/")
async def test(request):
return json({"test": True})
in flask:
@app.route("/")
def hello():
return "Hello World!"
Since each function takes a request argument, why not set it as a global variable.
Could you tell me the reason why you don't do this๏ผthank you
I think it'd be useful to have sanic in the TechEmpower benchmarks so that more users can discover it.
The instructions to get in are found here:
https://www.techempower.com/benchmarks/#section=code
And sample applications can be found here:
https://github.com/TechEmpower/FrameworkBenchmarks
When I see a lightweight framework like this, I compare it to something like Bottle before Flask. Would be nice to see how it compares with the rest of the frameworks up there.
Content type of JSON is always utf-8, so
content_type="application/json; charset=utf-8")
should be
content_type="application/json")
STATUS_CODES dict in response.py should include 201 as CREATED.
I was a little too hasty updating the blueprints documentation for middleware/exceptions, and just realized that middlewares and exceptions registered through a blueprint decorator are applied to all routes.
Is this intended behaviour? If so, then the the blueprint documentation must be updated once more.
Alternative behaviour: middleware registered on a blueprint, are only applied to routes for that blueprint.
Some considerations:
Sanic attempts to register signal handlers here:
https://github.com/channelcat/sanic/blob/master/sanic/server.py#L227
But using the asyncio event loop (as is the fallback when uvloop can't be imported) does not implement signal handlers. See https://docs.python.org/3/library/asyncio-eventloops.html#windows where it states this, and the code at https://github.com/python/asyncio/blob/master/asyncio/events.py#L480
Commenting out the signal lines in sanic allows sanic to run on windows (yay) but then you can't Ctrl-C out of it, you must kill the python process
Create a new example of how to use SQLalchemy with Sanic. It can be a simple python file or an organized project in its own folder, whichever is easiest to understand and gets someone started on the right track.
Example of sqlalchemy + aiopg:
https://aiopg.readthedocs.io/en/stable/#sqlalchemy-and-aiopg
More research needs to be done on integration with other popular DBs - I'm not sure if this will up the difficulty so I tagged it as both beginner and intermediate.
Cookie support is needed for both requests and responses.
Request:
cookie_value = request.cookies['cookie_name']
Response:
response.cookies['cookie_name'] = 'cookie_value'
response.cookies.set(name='cookie_name', value='cookie_value', secure=True,\
http_only=True, domain='.my-domain.com', path='/my-path', \
expires=datetime.now(), max_age=timedelta(days=1))
Using https://github.com/channelcat/sanic/blob/master/examples/simple_server.py adding workers=4
to run fails. But works fine otherwise:
2016-10-18 17:33:20,078: INFO: Goin' Fast @ http://0.0.0.0:8000
2016-10-18 17:33:20,078: INFO: Spinning up 4 workers...
2016-10-18 17:33:20,115: ERROR: Unable to start server: [Errno 22] Invalid argument
2016-10-18 17:33:20,126: ERROR: Unable to start server: [Errno 22] Invalid argument
2016-10-18 17:33:20,140: ERROR: Unable to start server: [Errno 22] Invalid argument
2016-10-18 17:33:20,150: ERROR: Unable to start server: [Errno 22] Invalid argument
Will try and debug more in a bit, but not sure what is going on yet.
Oh, and running the latest version from pip, have not pulled the latest git, if there has been a fix already.
It would be nice to have Swagger/OpenAPI support. I'm not sure what the most intuitive way to implement this is.
Some examples, for inspiration:
TornadoWeb is a Python web framework and asynchronous networking library.
Sure on Py3
What do you think about msgpack as json lib? As I know it is faster than ujson.
https://gist.github.com/cactus/4073643
https://blog.ionelmc.ro/2015/11/22/memory-use-and-speed-of-json-parsers/
https://gist.github.com/msiedlarek/4985748#file-ujson_vs_msgpack-py
(my results:
json: 32.72526153300714
ujson: 33.44454480899731
msgpack: 9.162779016012792)
I think it will be great to replace ujson to msgpack or just move ujson to another level of abstraction to have ability to choose between msgpack or ujson or smth else.
Hi, Thanks for the great work on Sanic!
I just started using it for a small project of mine. One bug which i ran into was its inability to parse parameters with punctuation in them, like so:
@app.route('/entries/domain/<domain>')
async def get_entries_for_domain(request, domain):
...
GET http://0.0.0.0:8000/entries/domain/kernel.org
Error: Requested URL /entries/domain/kernel.org not found
But at the same time fetching the /entries/domain/kernel_org
endpoint works.
Any way to work around this?
@channelcat As you've left no identifying information about yourself for correspondence about sanic I have no choice but to write you here. I authored Yosai and would like to see how it could be used to secure sanic applications.
I've read the source code of route part and find https://github.com/channelcat/sanic/blob/master/sanic/router.py#L82 , I wonder what's the unhashable url and if you can give an example :)
Hiya,
One thing that's not clear to me from the documentation is how users should be expected to handle app redeployments (without dropping existing connections). Presumably you'd need to bring up the new servers on a different port, switch the load balancer, and then (gracefully) stop the existing server.
(Also related to #61 since graceful reloads are one of the benefits of running an application framework underneath a server such as gunicorn.)
in: https://github.com/channelcat/sanic/blob/master/sanic/sanic.py#L257 you spin every 0.3 seconds checking if the event has been set, why not just wait on the event?
I was hoping this would be a one for one replacement of Flask, but the configurations don't seem to line up and I can't find any documentation on configuration.
Any help would be appreciated. I am willing to help if I can.
aiohttp and pytest is required for testing/development (python -m pytest tests
), but they are not included in a development requirements.txt. #20 solves this.
while return json(doc)
, doc
is fetched from mongodb.
server.py, line 137-139:
If the response is malformed, Sanic will log an error (thankfully), but will not return any kind of response (simply killing the connection).
Sanic should generate an exception that can be handled by the error handler, and ultimately return a 500.
Note that this can be generated by attempting to return a Flask-type tuple instead of a Sanic response object.
I actually don't know if it requires a custom requests library or if it's something that can be done "natively" with sanic, but being able to do requests queries async would be awesome. Then you don't have to worry about blocking when doing a sloooow requests.post(...)
.
Also, something I'm personally interested in, is the ability to use elasticsearch in an async matter.
Hey, awesome job!
I would like to know if it`s possible to run tasks in the background (the tasks of course must be async).
For examples:
Is that possible and how do you recommend me to do that?
Thanks!
Benchmarks should use uWSGI + Nginx.
Create a new example of how to use peewee-async with Sanic. It can be a simple python file or an organized project in its own folder, whichever is easiest to understand and gets someone started on the right track.
Peewee-async docs:
https://peewee-async.readthedocs.io/en/latest/
Via contributing.md
:
One of the main goals of Sanic is speed. Code that lowers the performance of Sanic without significant gains in usability, security, or features may not be merged.
I'm afraid to make any "big" change attempts without knowing the exact way you're running the speed tests.
Add blueprint support, as it makes maintaining and separating larger applications much easier.
I'm currently working on a prototype implementing basic blueprint functionality. For now, only uri's (with blueprint url prefixes) will be supported, not handling blueprint specific static/template endpoints.
I aim to have a PR ready some time tomorrow, but I need to formulate some tests and documentation first.
My current working example looks like this:
from sanic import Sanic
from sanic import Blueprint
from sanic.response import json, text
app = Sanic(__name__)
blueprint = Blueprint('name', url_prefix='/my_blueprint')
blueprint2 = Blueprint('name2', url_prefix='/my_blueprint2')
@blueprint.route('/foo')
async def foo(request):
return json({'msg': 'hi from blueprint'})
@blueprint2.route('/foo')
async def foo2(request):
return json({'msg': 'hi from blueprint2'})
app.register_blueprint(blueprint)
app.register_blueprint(blueprint2)
app.run(host="0.0.0.0", port=8000, debug=True)
Yielding the following routes to the application:
/my_blueprint/foo
/my_blueprint2/foo
What do you think about integrate templates (jinja2?) into sanic core? I think the popularity of django and flask largely depends on their ability to write and distribute independent apps, which contains its own routes, handlers, templates and static files. Sanic has all of this except of templates.
If you agree, I suggest the next api:
render_string('index.html', context)
render('index.html', context)
@app.context_processor
@bp.context_processor
@app.template('index.html')
@bp.template('index.html')
C:\Users\martijn>pip install https://github.com/channelcat/sanic/archive/master.zip
Collecting https://github.com/channelcat/sanic/archive/master.zip
Downloading https://github.com/channelcat/sanic/archive/master.zip
| 30kB 364kB/s
Collecting uvloop>=0.5.3 (from Sanic==0.1.0)
Downloading uvloop-0.5.4.tar.gz (1.9MB)
100% |################################| 1.9MB 180kB/s
Complete output from command python setup.py egg_info:
Traceback (most recent call last):
File "<string>", line 1, in <module>
File "C:\Users\martijn\AppData\Local\Temp\pip-build-gylxe2o1\uvloop\setup.py", line 9, in <module>
raise RuntimeError('uvloop does not support Windows at the moment')
RuntimeError: uvloop does not support Windows at the moment
----------------------------------------
Command "python setup.py egg_info" failed with error code 1 in C:\Users\martijn\AppData\Local\Temp\pip-build-gylxe2o1\uvloop\
I know this is technically a uvloop issue, but since it affects this repo as well I suggest making an alternative for windows users
the speed dropped significantly to roughly 3k on my machine compared to 33k
Instead of saying return text(..)
in a route, allow return 'my text'
by inferring the response type in write_response
.
sanic/server.py:
class HttpProtocol
...
...
def write_response(self, response):
try:
keep_alive = self.parser.should_keep_alive() and not self.signal.stopped
try:
self.transport.write(response.output(self.request.version, keep_alive, self.request_timeout))
except AttributeError:
# attempt to send the response as a text response
if isinstance(response, str):
response = text(response)
self.transport.write(response.output(self.request.version, keep_alive, self.request_timeout))
else:
raise
if not keep_alive:
self.transport.close()
else:
self.cleanup()
except Exception as e:
self.bail_out("Writing request failed, connection closed {}".format(e))
Noticed a fair amount of TODOs in the code, would be great to prioritize what needs to be done. Maybe ranking it in terms of difficulty as well for contributors who are at the beginner level all the way to expert?
While sanic is super fast on a single process, it still leaves the other cores on the machine idle. I had hoped being 'flask like' it would drop into uWSGI just as easily but that does not appear to be the case in my experimentation. Attempting to use it as a drop in replacement to a flask app returns TypeError: 'Sanic' object is not callable
I do not know if this is even feasible while still keeping the speed improvements, but compatibility with uWSGI, or some other method to fully utilize the CPU of a server would be extremely useful. If there is already a method of doing this, I was unable to find it in the examples or docs and additional information on the method would be extremely useful.
Sending binary files shouldn't be part of the project boiler plate, I think it should be included in the framework itself. This is a simplified version I made from Flask's send_file
import os
import mimetypes
from sanic.response import HTTPResponse
def sendfile(location, mimetype=None, add_etags=True):
headers = {}
filename = os.path.split(location)[-1]
with open(location, 'rb') as ins_file:
out_stream = ins_file.read()
if add_etags:
headers['ETag'] = '{}-{}-{}'.format(
int(os.path.getmtime(location)),
hex(os.path.getsize(location)),
adler32(location.encode('utf-8')) & 0xffffffff)
mimetype = mimetype or mimetypes.guess_type(filename)[0] or 'text/plain'
return HTTPResponse(status=200,
headers=headers,
content_type=mimetype,
body_bytes=out_stream)
Maybe a travis CI can be setup to automatically run tests on PR (including flake8 plz) and to also automate the submittal to PyPI.
Is there any way to mix sanic with gunicorn? Gunicorn has signals to increase/decrease workers and a bunch of other features that are useful in running a service in production.
Hi! really interesting project :).
I'm developing an asynchronous cache https://github.com/argaen/aiocache. The project is quite new but I'm looking for feedback and new use cases which will help to improve the interface and its usability.
I want the project to be really easy to integrate with other frameworks so I would really appreciate opinions on it :P.
Thanks a lot! :)
Can i use subdomain routing with blueprints? Basically i have more than two or three modules that i want to be on different subdomains using Blueprints. Below is the code for doing it in flask, but can i do something like this in sanic?
# -*- coding: utf-8 -*-
from flask import Flask, Blueprint
app = Flask(__name__)
app.config.DEBUG = True
www = Blueprint('www', 'www', subdomain='www')
sub = Blueprint('sub', 'sub', subdomain='sub')
@www.route('/')
def www_hello():
return 'www.www_hello'
@sub.route('/')
def sub_hello():
return 'sub.sub_hello'
app.register_blueprint(www)
app.register_blueprint(sub)
if __name__ == '__main__':
app.run(host='127.0.0.1', port=8888, debug=True)
Unreachable code:
# sanic/sanic.py
76 # Detect which way this was called, @middleware or @middleware('AT')
77 if len(args) == 1 and len(kwargs) == 0 and callable(args[0]):
78 return register_middleware(args[0])
79 else:
80 attach_to = args[0]
81 return register_middleware
82 ################################## ENDS HERE
83 if isinstance(middleware, FunctionType):
84 middleware = Middleware(process_request=middleware)
85
86 return middleware
I think there need add a requirement of 'aiohttp' in requirements.txt.
@bp.route('/')
async def bp_root():
return json({'my': 'blueprint'})
should be
@bp.route('/')
async def bp_root(request):
return json({'my': 'blueprint'})
Since the event loop is created in server.serve
it could be beneficial to expose passing a pre-allocated event loop that could be used before the server starts to enable database connections and such.
Not too sure if this is planned, but figured it would help in terms of further contributions as the codebase continues to grow.
Maybe a plugin or a builtin support for websocket will be great.
Sanic doesn't have a logger like flask, so how to use logging in it
https://github.com/SunDwarf/Kyoukai โ uses asyncio + Ashpalt (and is also quite Flask-ish)
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.