<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/"
    xmlns:atom="http://www.w3.org/2005/Atom" xmlns:media="http://search.yahoo.com/mrss/" version="2.0">
    <channel>
        
        <title>
            <![CDATA[ Sanic - freeCodeCamp.org ]]>
        </title>
        <description>
            <![CDATA[ Browse thousands of programming tutorials written by experts. Learn Web Development, Data Science, DevOps, Security, and get developer career advice. ]]>
        </description>
        <link>https://www.freecodecamp.org/news/</link>
        <image>
            <url>https://cdn.freecodecamp.org/universal/favicons/favicon.png</url>
            <title>
                <![CDATA[ Sanic - freeCodeCamp.org ]]>
            </title>
            <link>https://www.freecodecamp.org/news/</link>
        </image>
        <generator>Eleventy</generator>
        <lastBuildDate>Thu, 02 Jul 2026 20:11:57 +0000</lastBuildDate>
        <atom:link href="https://www.freecodecamp.org/news/tag/sanic/rss.xml" rel="self" type="application/rss+xml" />
        <ttl>60</ttl>
        
            <item>
                <title>
                    <![CDATA[ How to make your code fast and asynchronous with Python and Sanic ]]>
                </title>
                <description>
                    <![CDATA[ By Davit Tovmasyan Hello everybody. In this article I’ll talk about building simple asynchronous projects with the Sanic framework. Goin’ Fast Introduction Sanic is a very flask-like open-source Python web server and web framework with more than 10K... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/goin-fast-and-asynchronous-with-python-and-sanic-387d722f3668/</link>
                <guid isPermaLink="false">66c34ba99972b7c5c7624e68</guid>
                
                    <category>
                        <![CDATA[ Sanic ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Productivity ]]>
                    </category>
                
                    <category>
                        <![CDATA[ General Programming ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Python ]]>
                    </category>
                
                    <category>
                        <![CDATA[ tech  ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ freeCodeCamp ]]>
                </dc:creator>
                <pubDate>Thu, 28 Feb 2019 08:57:06 +0000</pubDate>
                <media:content url="https://cdn-media-1.freecodecamp.org/images/1*vJxAS5gEDCUgnTntr5eSRg.jpeg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>By Davit Tovmasyan</p>
<p>Hello everybody. In this article I’ll talk about building simple asynchronous projects with the Sanic framework.</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/F0Jro1PM0OTKI0on7Hz0sEIFNlIb9JWZ58JO" alt="Image" width="600" height="337" loading="lazy">
<em>Goin’ Fast</em></p>
<h3 id="heading-introduction">Introduction</h3>
<p><a target="_blank" href="https://sanicframework.org/">Sanic</a> is a very flask-like open-source Python web server and web framework with more than <a target="_blank" href="https://github.com/huge-success/sanic">10K stars</a> that’s written to go fast. It allows the usage of <code>async/await</code> syntax added in Python 3.5 (<a target="_blank" href="https://docs.python.org/3/library/asyncio-task.html">read more</a>), which makes your code <a target="_blank" href="https://medium.com/vaidikkapoor/understanding-non-blocking-i-o-with-python-part-1-ec31a2e2db9b">non-blocking</a> and speedy.</p>
<p>Sanic has pretty good <a target="_blank" href="https://sanic.readthedocs.io/en/latest/">documentation</a> and it’s maintained by the community, for the community.</p>
<blockquote>
<p>The goal of the project is to provide a simple way to get a highly performant HTTP server up and running that is easy to build, to expand, and ultimately to scale.</p>
</blockquote>
<h3 id="heading-requirements">Requirements</h3>
<p>Before we start, let’s install some packages and make sure that we have everything ready for the development of this project.</p>
<p><em>Note: Source code is available in my <a target="_blank" href="https://github.com/davitovmasyan/sanic-project">github.com</a> repository. For each step there is a corresponding commit.</em></p>
<h4 id="heading-prerequisites">Prerequisites:</h4>
<ul>
<li>Python3.6+</li>
<li><a target="_blank" href="https://github.com/pypa/pipenv">pipenv</a> (you can use any other package installer)</li>
<li><a target="_blank" href="https://www.postgresql.org/">PostgreSQL</a> (for database, can also be MySQL or SQLite)</li>
</ul>
<h4 id="heading-packages">Packages:</h4>
<ul>
<li><a target="_blank" href="https://pypi.org/project/secure/">secure</a> is a lightweight package that adds optional security headers and cookie attributes for Python web frameworks.</li>
<li><a target="_blank" href="https://pypi.org/project/environs/">environs</a> is a Python library for parsing environment variables. It allows you to store configuration separate from your code, as per <a target="_blank" href="https://12factor.net/config">The Twelve-Factor App</a> methodology.</li>
<li><a target="_blank" href="https://github.com/jamesstidard/sanic-envconfig">sanic-envconfig</a> is and extension that helps you bring command line &amp; environment variables into your Sanic config.</li>
<li><a target="_blank" href="https://pypi.org/project/databases/">databases</a> is a Python package that allows you to make queries using the powerful <a target="_blank" href="https://docs.sqlalchemy.org/en/latest/core/">SQLAlchemy Core</a> expression language, and provides support for PostgreSQL, MySQL, and SQLite.</li>
</ul>
<p>Let’s create an empty directory and initialize an empty <code>Pipfile</code> there.</p>
<pre><code>pipenv  -- python python3<span class="hljs-number">.6</span>
</code></pre><p>Install all necessary packages using <strong>pipenv</strong> commands below.</p>
<pre><code>pipenv install sanic secure environs sanic-envconfig
</code></pre><p>For database:</p>
<pre><code>pipenv install databases[postgresql]
</code></pre><p>Choices are <strong>postgresql, mysql, sqlite.</strong></p>
<h3 id="heading-structure">Structure</h3>
<p>Now let’s create some files and folders where we will write our actual code.</p>
<pre><code>├── .env├── Pipfile├── Pipfile.lock├── setup.py└── project    ├── __init__.py    ├── __main__.py    ├── main.py    ├── middlewares.py    ├── routes.py    ├── settings.py    └── tables.py
</code></pre><p>We will use the <code>setup.py</code> file to make the <code>project</code> folder available as a package in our code.</p>
<pre><code><span class="hljs-keyword">from</span> setuptools <span class="hljs-keyword">import</span> setupsetup(    name=<span class="hljs-string">'project'</span>,)
</code></pre><p><em>Installing…</em></p>
<pre><code>pipenv install -e .
</code></pre><p>In the <code>.env</code> file, we’ll store some global variables like the database connection URL.</p>
<p><code>__main__.py</code> is created for making our <code>project</code> package executable from the command-line.</p>
<pre><code>pipenv run python -m project
</code></pre><h3 id="heading-initialization">Initialization</h3>
<p>Let’s do our first call in <strong><strong>main</strong>.py</strong> file.</p>
<pre><code><span class="hljs-keyword">from</span> project.main <span class="hljs-keyword">import</span> initinit()
</code></pre><p>This is the beginning of our application. Now we need to create the <code>init</code> function inside of <strong>main.py</strong> file.</p>
<pre><code><span class="hljs-keyword">from</span> sanic <span class="hljs-keyword">import</span> Sanicapp = Sanic(__name__)def init():    app.run(host=<span class="hljs-string">'0.0.0.0'</span>, port=<span class="hljs-number">8000</span>, debug=True)
</code></pre><p>Simply creating the app from the <em>Sanic</em> class we can run it specifying <strong>host</strong>, <strong>port</strong> and optional <strong>debug</strong> keyword argument.</p>
<p><em>Running…</em></p>
<pre><code>pipenv run python -m project
</code></pre><p><img src="https://cdn-media-1.freecodecamp.org/images/7GwhssZorNRLRt-O9V-Dlm0E9VCqTFqNeOE0" alt="Image" width="680" height="530" loading="lazy">
<em>Sanic console output</em></p>
<p>This is how a successful output should look in your Sanic app. If you open <a target="_blank" href="http://0.0.0.0:8000">http://0.0.0.0:8000</a> on your browser you’ll see</p>
<blockquote>
<p>Error: Requested URL / not found</p>
</blockquote>
<p>We haven’t created any <strong>routes</strong> yet, so it’s fine for now. We will add some routes below.</p>
<h3 id="heading-settings">Settings</h3>
<p>Now we can modify the environment and settings. We need to add some variables in the <strong>.env</strong> file, read them, and pass to Sanic app config.</p>
<p><strong><em>.env</em></strong> <em>file.</em></p>
<pre><code>DEBUG=TrueHOST=<span class="hljs-number">0.0</span><span class="hljs-number">.0</span><span class="hljs-number">.0</span>POST=<span class="hljs-number">8000</span>
</code></pre><p><em>Configuration…</em></p>
<pre><code><span class="hljs-keyword">from</span> sanic <span class="hljs-keyword">import</span> Sanic
</code></pre><pre><code><span class="hljs-keyword">from</span> environs <span class="hljs-keyword">import</span> Envfrom project.settings <span class="hljs-keyword">import</span> Settings
</code></pre><pre><code>app = Sanic(__name__)
</code></pre><pre><code>def init():    env = Env()    env.read_env()        app.config.from_object(Settings)    app.run(        host=app.config.HOST,         port=app.config.PORT,         debug=app.config.DEBUG,        auto_reload=app.config.DEBUG,        )
</code></pre><p><strong><em>settings.py</em></strong> <em>file.</em></p>
<pre><code><span class="hljs-keyword">from</span> sanic_envconfig <span class="hljs-keyword">import</span> EnvConfigclass Settings(EnvConfig):    DEBUG: bool = True    HOST: str = <span class="hljs-string">'0.0.0.0'</span>    PORT: int = <span class="hljs-number">8000</span>
</code></pre><p>Please note that I’ve added an optional <strong>auto_reload</strong> argument which will activate or deactivate the Automatic Reloader.</p>
<h3 id="heading-database">Database</h3>
<p>Now it’s time to setup a database.</p>
<p>One little note about the <strong>databases</strong> package before we go ahead:</p>
<blockquote>
<p><strong>databases</strong> package uses <a target="_blank" href="https://github.com/MagicStack/asyncpg">asyncpg</a> which is an asynchronous interface library for PostgreSQL. It’s pretty fast. See results below.</p>
</blockquote>
<p><img src="https://cdn-media-1.freecodecamp.org/images/RvldCRR3gSuI4UKswmylnrJYrIDQhQ9wetEd" alt="Image" width="800" height="338" loading="lazy"></p>
<p>We will use two of Sanic’s <a target="_blank" href="https://sanic.readthedocs.io/en/latest/sanic/middleware.html#listeners">listeners</a> where we will specify database connect and disconnect operations. Here are the listeners that we are going to use:</p>
<ul>
<li><strong>after_server_start</strong></li>
<li><strong>after_server_stop</strong></li>
</ul>
<p><strong><em>main.py</em></strong> <em>file.</em></p>
<pre><code><span class="hljs-keyword">from</span> sanic <span class="hljs-keyword">import</span> Sanic
</code></pre><pre><code><span class="hljs-keyword">from</span> databases <span class="hljs-keyword">import</span> Database
</code></pre><pre><code><span class="hljs-keyword">from</span> environs <span class="hljs-keyword">import</span> Envfrom project.settings <span class="hljs-keyword">import</span> Settings
</code></pre><pre><code>app = Sanic(__name__)
</code></pre><pre><code>def setup_database():    app.db = Database(app.config.DB_URL)    @app.listener(<span class="hljs-string">'after_server_start'</span>)    <span class="hljs-keyword">async</span> def connect_to_db(*args, **kwargs):        <span class="hljs-keyword">await</span> app.db.connect()    @app.listener(<span class="hljs-string">'after_server_stop'</span>)    <span class="hljs-keyword">async</span> def disconnect_from_db(*args, **kwargs):        <span class="hljs-keyword">await</span> app.db.disconnect()
</code></pre><pre><code>def init():    env = Env()    env.read_env()        app.config.from_object(Settings)
</code></pre><pre><code>    setup_database()
</code></pre><pre><code>    app.run(        host=app.config.HOST,         port=app.config.PORT,         debug=app.config.DEBUG,        auto_reload=app.config.DEBUG,        )
</code></pre><p>Once more thing. We need to specify <strong>DB_URL</strong> in project settings and environment.</p>
<p><strong><em>.env</em></strong> <em>file.</em></p>
<pre><code>DEBUG=TrueHOST=<span class="hljs-number">0.0</span><span class="hljs-number">.0</span><span class="hljs-number">.0</span>POST=<span class="hljs-number">8000</span>DB_URL=postgresql:<span class="hljs-comment">//postgres:postgres@localhost/postgres</span>
</code></pre><p><em>And <strong>settings.py</strong> file.</em></p>
<pre><code><span class="hljs-keyword">from</span> sanic_envconfig <span class="hljs-keyword">import</span> EnvConfigclass Settings(EnvConfig):    DEBUG: bool = True    HOST: str = <span class="hljs-string">'0.0.0.0'</span>    PORT: int = <span class="hljs-number">8000</span>    DB_URL: str = <span class="hljs-string">''</span>
</code></pre><p>Make sure that <strong>DB_URL</strong> is correct and your database is running. Now you can access to database using <strong>app.db.</strong> See more detailed information in the next section.</p>
<h3 id="heading-tables">Tables</h3>
<p>Now we have a connection to our database and we can try to do some SQL queries.</p>
<p>Let’s declare a table in <strong>tables.py</strong> file using SQLAlchemy.</p>
<pre><code><span class="hljs-keyword">import</span> sqlalchemymetadata = sqlalchemy.MetaData()books = sqlalchemy.Table(    <span class="hljs-string">'books'</span>,    metadata,    sqlalchemy.Column(<span class="hljs-string">'id'</span>, sqlalchemy.Integer, primary_key=True),    sqlalchemy.Column(<span class="hljs-string">'title'</span>, sqlalchemy.String(length=<span class="hljs-number">100</span>)),    sqlalchemy.Column(<span class="hljs-string">'author'</span>, sqlalchemy.String(length=<span class="hljs-number">60</span>)),)
</code></pre><p>Here I assume that you already have a <strong>migrated</strong> database with a <strong>books</strong> table in it. For creating database migrations, I recommend that you use <a target="_blank" href="https://alembic.sqlalchemy.org/">Alembic</a> which is a lightweight and easy-to-use tool that you can use with the SQLAlchemy Database Toolkit for Python.</p>
<p>Now we can use any <a target="_blank" href="https://docs.sqlalchemy.org/en/latest/core/">SQLAlchemy core</a> queries. Check out some examples below.</p>
<pre><code># Executing manyquery = books.insert()values = [    {<span class="hljs-string">"title"</span>: <span class="hljs-string">"No Highway"</span>, <span class="hljs-string">"author"</span>: <span class="hljs-string">"Nevil Shute"</span>},    {<span class="hljs-string">"title"</span>: <span class="hljs-string">"The Daffodil"</span>, <span class="hljs-string">"author"</span>: <span class="hljs-string">"SkyH. E. Bates"</span>},]<span class="hljs-keyword">await</span> app.db.execute_many(query, values)# Fetching multiple rowsquery = books.select()rows = <span class="hljs-keyword">await</span> app.db.fetch_all(query)# Fetch single rowquery = books.select()row = <span class="hljs-keyword">await</span> app.db.fetch_one(query)
</code></pre><h3 id="heading-routes">Routes</h3>
<p>Now we need to setup routes. Let’s go to <strong>routes.py</strong> and add a new route for books.</p>
<pre><code><span class="hljs-keyword">from</span> sanic.response <span class="hljs-keyword">import</span> json
</code></pre><pre><code><span class="hljs-keyword">from</span> project.tables <span class="hljs-keyword">import</span> books
</code></pre><pre><code>def setup_routes(app):    @app.route(<span class="hljs-string">"/books"</span>)    <span class="hljs-keyword">async</span> def book_list(request):        query = books.select()        rows = <span class="hljs-keyword">await</span> request.app.db.fetch_all(query)        <span class="hljs-keyword">return</span> json({            <span class="hljs-string">'books'</span>: [{row[<span class="hljs-string">'title'</span>]: row[<span class="hljs-string">'author'</span>]} <span class="hljs-keyword">for</span> row <span class="hljs-keyword">in</span> rows]        })
</code></pre><p>Of course we need to call <strong>setup_routes</strong> in <strong>init</strong> to make it work.</p>
<pre><code><span class="hljs-keyword">from</span> project.routes <span class="hljs-keyword">import</span> setup_routes
</code></pre><pre><code>app = Sanic(__name__)
</code></pre><pre><code>def init():    ...    app.config.from_object(Settings)    setup_database()    setup_routes(app)    ...
</code></pre><p><em>Requesting…</em></p>
<pre><code>$ curl localhost:<span class="hljs-number">8000</span>/books{<span class="hljs-string">"books"</span>:[{<span class="hljs-string">"No Highway"</span>:<span class="hljs-string">"Nevil Shute"</span>},{<span class="hljs-string">"The Daffodil"</span>:<span class="hljs-string">"SkyH. E. Bates"</span>}]}
</code></pre><h3 id="heading-middlewares">Middlewares</h3>
<p>What about checking the <strong>response</strong> headers and seeing what we can add or fix there?</p>
<pre><code>$ curl -I localhost:<span class="hljs-number">8000</span>Connection: keep-aliveKeep-Alive: <span class="hljs-number">5</span>Content-Length: <span class="hljs-number">32</span>Content-Type: text/plain; charset=utf<span class="hljs-number">-8</span>
</code></pre><p>As you can see we need some security improvements. There are some missing headers such as <strong>X-XSS-Protection, Strict-Transport-Security</strong>… so let’s take care of them using a combination of <a target="_blank" href="https://sanic.readthedocs.io/en/latest/sanic/middleware.html#middleware">middlewares</a> and <strong>secure</strong> packages.</p>
<p><strong><em>middlewares.py</em></strong> <em>file.</em></p>
<pre><code><span class="hljs-keyword">from</span> secure <span class="hljs-keyword">import</span> SecureHeaderssecure_headers = SecureHeaders()def setup_middlewares(app):    @app.middleware(<span class="hljs-string">'response'</span>)    <span class="hljs-keyword">async</span> def set_secure_headers(request, response):        secure_headers.sanic(response)
</code></pre><p><em>Setting up middlewares in <strong>main.py</strong> file.</em></p>
<pre><code><span class="hljs-keyword">from</span> project.middlewares <span class="hljs-keyword">import</span> setup_middlewares
</code></pre><pre><code>app = Sanic(__name__)
</code></pre><pre><code>def init():    ...    app.config.from_object(Settings)    setup_database()    setup_routes(app)    setup_middlewares(app)    ...
</code></pre><p><em>The result is:</em></p>
<pre><code>$ curl -I localhost:<span class="hljs-number">8000</span>/booksConnection: keep-aliveKeep-Alive: <span class="hljs-number">5</span>Strict-Transport-Security: max-age=<span class="hljs-number">63072000</span>; includeSubdomainsX-Frame-Options: SAMEORIGINX-XSS-Protection: <span class="hljs-number">1</span>; mode=blockX-Content-Type-Options: nosniffReferrer-Policy: no-referrer, strict-origin-when-cross-originPragma: no-cacheExpires: <span class="hljs-number">0</span>Cache-control: no-cache, no-store, must-revalidate, max-age=<span class="hljs-number">0</span>Content-Length: <span class="hljs-number">32</span>Content-Type: text/plain; charset=utf<span class="hljs-number">-8</span>
</code></pre><p>As I promised at the beginning, there is a <a target="_blank" href="https://github.com/davitovmasyan/sanic-project">github repository</a> for each <a target="_blank" href="https://github.com/davitovmasyan/sanic-project/tags">section</a> in this article. Hope this small tutorial helped you to get started with Sanic. There are still many unexplored features in the Sanic framework that you can find and check out in the <a target="_blank" href="https://sanic.readthedocs.io/en/latest/">documentation</a>.</p>
<p><a target="_blank" href="https://github.com/davitovmasyan/sanic-project"><strong>davitovmasyan/sanic-project</strong></a><br><a target="_blank" href="https://github.com/davitovmasyan/sanic-project">_Goin' Fast and asynchronous with Python and Sanic! - davitovmasyan/sanic-project_github.com</a></p>
<p>If you have thoughts on this, be sure to leave a comment.</p>
<p>If you found this article helpful, give me some claps ?</p>
<p>Thanks for reading. Go Fast with Sanic and good luck!!!</p>
 ]]>
                </content:encoded>
            </item>
        
    </channel>
</rss>
