Git Product home page Git Product logo

sanic's Introduction

Sanic | Build fast. Run fast.

Sanic | Build fast. Run fast.

Build
Tests
Docs
UserGuide Documentation
Package
Support
Stats

Sanic is a Python 3.8+ web server and web framework that's written to go fast. It allows the usage of the async/await syntax added in Python 3.5, which makes your code non-blocking and speedy.

Sanic is also ASGI compliant, so you can deploy it with an alternative ASGI webserver.

Source code on GitHub | Help and discussion board | User Guide | Chat on Discord

The project is maintained by the community, for the community. Contributions are welcome!

The goal of the project is to provide a simple way to get up and running a highly performant HTTP server that is easy to build, to expand, and ultimately to scale.

Sponsor

Check out open collective to learn more about helping to fund Sanic.

Installation

pip3 install sanic

Sanic makes use of uvloop and ujson to help with performance. If you do not want to use those packages, simply add an environmental variable SANIC_NO_UVLOOP=true or SANIC_NO_UJSON=true at install time.

$ export SANIC_NO_UVLOOP=true
$ export SANIC_NO_UJSON=true
$ pip3 install --no-binary :all: sanic

Note

If you are running on a clean install of Fedora 28 or above, please make sure you have the redhat-rpm-config package installed in case if you want to use sanic with ujson dependency.

Hello World Example

from sanic import Sanic
from sanic.response import json

app = Sanic("my-hello-world-app")

@app.route('/')
async def test(request):
    return json({'hello': 'world'})

if __name__ == '__main__':
    app.run()

Sanic can now be easily run using sanic hello.app.

[2018-12-30 11:37:41 +0200] [13564] [INFO] Goin' Fast @ http://127.0.0.1:8000
[2018-12-30 11:37:41 +0200] [13564] [INFO] Starting worker [13564]

And, we can verify it is working: curl localhost:8000 -i

HTTP/1.1 200 OK
Connection: keep-alive
Keep-Alive: 5
Content-Length: 17
Content-Type: application/json

{"hello":"world"}

Now, let's go build something fast!

Minimum Python version is 3.8. If you need Python 3.7 support, please use v22.12LTS.

Documentation

User Guide, Changelog, and API Documentation can be found at sanic.dev.

Questions and Discussion

Ask a question or join the conversation.

Contribution

We are always happy to have new contributions. We have marked issues good for anyone looking to get started, and welcome questions on the forums. Please take a look at our Contribution guidelines.

sanic's People

Contributors

38elements avatar agoose77 avatar ahopkins avatar andreymal avatar antondnepr avatar archelyst avatar arnulfojr avatar ashleysommer avatar channelcat avatar chenjr0719 avatar chihweilhbird avatar frzk avatar harshanarayana avatar howie6879 avatar hramezani avatar jotagesales avatar jpiasetz avatar kdelwat avatar lixxu avatar messense avatar prryplatypus avatar r0fls avatar seemethere avatar sjsadowski avatar stopspazzing avatar subyraman avatar tronic avatar youknowone avatar yunstanford avatar zenixls2 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

sanic's Issues

Msgpack as an alternative to ujson

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.

Add benchmarking to Travis gate job?

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.

Missing requirements for testing/dev

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.

Feedback on cache layer

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! :)

Add Bottle.py + Gunicorn comparisons?

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.

Handling redployments

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.

  • Does sanic handle graceful redeployment without dropping connections?
  • Have I misunderstood how app redeployment should be handled with sanic?
  • Would this be worth documenting in the deployment section.

(Also related to #61 since graceful reloads are one of the benefits of running an application framework underneath a server such as gunicorn.)

asyncio signal handlers don't work on Windows

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

Example of using async requests

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.

way too anonymous

@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.

Code is indented with tabs instead of spaces

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.

Consider allowing a string response to be inferred as `text(..)`

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))

Examples - SQLAlchemy

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.

Blueprint support

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

Swagger/OpenAPI Support

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:

  • Flask-swagger - Uses YAML appended to docstring
  • Connexion - Reads YAML swagger doc files and hosts a swagger UI

Serving Static Content

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)

Unable to start with multiple workers.

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.

Route parameters with dots or other punctuation not working

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?

Unreachable code in sanic.py middleware

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

Document logging

Sanic doesn't have a logger like flask, so how to use logging in it

Prioritizing TODOs

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?

Subdomains in Blueprints

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) 

Travis CI?

Maybe a travis CI can be setup to automatically run tests on PR (including flake8 plz) and to also automate the submittal to PyPI.

Running tasks in background

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:

  1. I want a task that runs every 1 minute and do a REST request and save the results in global variables (so my REST endpoints will use that "cached" data)
  2. I want to read from kafka topic and save the latest result in a global variable (so my REST endpoints will use that "cached" data)

Is that possible and how do you recommend me to do that?
Thanks!

Configuration

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.

Failure to write request swallows problem

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.

Cookie Support

Cookie support is needed for both requests and responses.

Request:

  • Provide a cookie property with caching to self.parsed_cookies
  • optimally, it should just be a dictionary of cookie keys to cookie values, to be used like:
cookie_value = request.cookies['cookie_name']

Response:

  • Interface could look like:
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))
  • Ideally, this should update the Set-Cookies header of the response when cookies are set.

Gunicorn worker

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.

No request param in blueprint docs

@bp.route('/')
async def bp_root():
    return json({'my': 'blueprint'})

should be

@bp.route('/')
async def bp_root(request):
    return json({'my': 'blueprint'})

Include script to run performance tests

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.

Multiple CPU Core Usage?

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.

Templates support

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')

Blueprint middleware applied globally

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:

  • should middleware applied to the app-object (instance of Sanic) also be applied to blueprint middleware?
  • if so, how will ordering be handled?

Request argument as a global variable

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

Incompatible with windows

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

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.