Django3.0 異步通信初體驗(yàn)(小結(jié))
此前博主曾經(jīng)寫(xiě)過(guò)一篇博文,介紹了Django3.0的新特性,其中最主要的就是加入對(duì)ASGI的支持,實(shí)現(xiàn)全雙工的異步通信。
2019年12月2日,Django終于正式發(fā)布了3.0版本。懷著無(wú)比的期待,我們來(lái)嘗試一下吧!
(附ASGI官方文檔地址:https://asgi.readthedocs.io/en/latest/extensions.html)
一、創(chuàng)建Django3工程
利用Pycharm的方便,直接通過(guò)virtualenv創(chuàng)建虛擬環(huán)境,并安裝Django3.0。
打開(kāi)控制臺(tái),看看都安裝了哪些庫(kù):
(venv) D:\work\for_test\django3>pip list Package Version ------ asgiref 3.2.3 Django 3.0 pip 10.0.1 pytz 2019.3 setuptools 39.1.0 sqlparse 0.3.0
除了pytz和sqlparse,又自動(dòng)安裝了asgiref。
asigref由Django軟件基金會(huì)開(kāi)發(fā)和維護(hù),是一個(gè)Django生態(tài)中的庫(kù)。
先啟動(dòng)一下服務(wù)器,看看Django是否正常運(yùn)行:
沒(méi)毛病,可以把服務(wù)器關(guān)了!
二、學(xué)習(xí)官方文檔
畢竟是非常重要和復(fù)雜的新特性,先到官網(wǎng)取取經(jīng),看看文檔怎么寫(xiě)的。
找了一圈,What?就這么點(diǎn)東西?
先康康吧。
How to deploy with ASGI As well as WSGI, Django also supports deploying on ASGI, the emerging Python standard for asynchronous web servers and applications. Django's startproject management command sets up a default ASGI configuration for you, which you can tweak as needed for your project, and direct any ASGI-compliant application server to use. Django includes getting-started documentation for the following ASGI servers: How to use Django with Daphne How to use Django with Uvicorn The application object Like WSGI, ASGI has you supply an application callable which the application server uses to communicate with your code. It's commonly provided as an object named application in a Python module accessible to the server. The startproject command creates a file <project_name>/asgi.py that contains such an application callable. It's not used by the development server (runserver), but can be used by any ASGI server either in development or in production. ASGI servers usually take the path to the application callable as a string; for most Django projects, this will look like myproject.asgi:application. Warning While Django's default ASGI handler will run all your code in a synchronous thread, if you choose to run your own async handler you must be aware of async-safety. Do not call blocking synchronous functions or libraries in any async code. Django prevents you from doing this with the parts of Django that are not async-safe, but the same may not be true of third-party apps or Python libraries. Configuring the settings module When the ASGI server loads your application, Django needs to import the settings module — that's where your entire application is defined. Django uses the DJANGO_SETTINGS_MODULE environment variable to locate the appropriate settings module. It must contain the dotted path to the settings module. You can use a different value for development and production; it all depends on how you organize your settings. If this variable isn't set, the default asgi.py sets it to mysite.settings, where mysite is the name of your project. Applying ASGI middleware To apply ASGI middleware, or to embed Django in another ASGI application, you can wrap Django's application object in the asgi.py file. For example: from some_asgi_library import AmazingMiddleware application = AmazingMiddleware(application)
文檔短小無(wú)力,內(nèi)容稀少!
總結(jié)就以下幾點(diǎn):
- 不能用python manage.py runserver的方式啟動(dòng)ASGI服務(wù)器,這只會(huì)啟動(dòng)傳統(tǒng)的、默認(rèn)的WSGI服務(wù)器,也就是老版本的東西
- 要啟動(dòng)ASGI服務(wù)器,你需要使用Daphne或者Uvicorn。推薦使用Daphne,這是Django軟件基金會(huì)開(kāi)發(fā)的一個(gè)基于ASGI (HTTP/WebSocket)的服務(wù)器。
- 有一個(gè)myproject.asgi:application文件,是ASGI通信的接口,Django默認(rèn)自帶
- 你可以配置DJANGO_SETTINGS_MODULE 環(huán)境,或者使用默認(rèn)的your_project.settings
- 可以使用第三方ASGI中間件
再簡(jiǎn)單粗暴點(diǎn),全文的意思是,你需要安裝Daphne,然后調(diào)用Django的application來(lái)啟動(dòng)ASGI服務(wù)器。
好吧,我們看看Daphne,點(diǎn)擊Django給的連接,跳轉(zhuǎn)到相關(guān)頁(yè)面,內(nèi)容更少:
How to use Django with Daphne Daphne is a pure-Python ASGI server for UNIX, maintained by members of the Django project. It acts as the reference server for ASGI. Installing Daphne You can install Daphne with pip: python -m pip install daphne Running Django in Daphne When Daphne is installed, a daphne command is available which starts the Daphne server process. At its simplest, Daphne needs to be called with the location of a module containing an ASGI application object, followed by what the application is called (separated by a colon). For a typical Django project, invoking Daphne would look like: daphne myproject.asgi:application This will start one process listening on 127.0.0.1:8000. It requires that your project be on the Python path; to ensure that run this command from the same directory as your manage.py file.
翻譯過(guò)來(lái)就是:
- pip安裝daphne
- 執(zhí)行daphne myproject.asgi:application命令,啟動(dòng)ASGI服務(wù)器
- 瀏覽器訪問(wèn)127.0.0.1:8000
咱們照做!
三、啟動(dòng)ASGI服務(wù)器
通過(guò)pip install daphne
即可安裝最新版本的daphne:
Collecting pycparser (from cffi!=1.11.3,>=1.8->cryptography>=2.7->autobahn>=0.18->daphne) Installing collected packages: idna, hyperlink, zope.interface, attrs, six, Automat, constantly, PyHamcrest, incremental, pycparser, cffi, cry ptography, pyopenssl, pyasn1, pyasn1-modules, service-identity, twisted, txaio, autobahn, daphne Successfully installed Automat-0.8.0 PyHamcrest-1.9.0 attrs-19.3.0 autobahn-19.11.1 cffi-1.13.2 constantly-15.1.0 cryptography-2.8 daphne-2.4. 0 hyperlink-19.0.0 idna-2.8 incremental-17.5.0 pyasn1-0.4.8 pyasn1-modules-0.2.7 pycparser-2.19 pyopenssl-19.1.0 service-identity-18.1.0 six-1 .13.0 twisted-19.10.0 txaio-18.8.1 zope.interface-4.7.1
為了安裝daphne,需要額外安裝這么多依賴(lài)包!我們?cè)賞ip list看一下:
(venv) D:\work\for_test\django3>pip list Package Version ---------------- ------- asgiref 3.2.3 attrs 19.3.0 autobahn 19.11.1 Automat 0.8.0 cffi 1.13.2 constantly 15.1.0 cryptography 2.8 daphne 2.4.0 Django 3.0 hyperlink 19.0.0 idna 2.8 incremental 17.5.0 pip 10.0.1 pyasn1 0.4.8 pyasn1-modules 0.2.7 pycparser 2.19 PyHamcrest 1.9.0 pyOpenSSL 19.1.0 pytz 2019.3 service-identity 18.1.0 setuptools 39.1.0 six 1.13.0 sqlparse 0.3.0 Twisted 19.10.0 txaio 18.8.1 zope.interface 4.7.1
不管了,就當(dāng)沒(méi)看見(jiàn)。
安裝成功后,我們會(huì)獲得一個(gè)daphne可執(zhí)行命令,下面我們來(lái)啟動(dòng)服務(wù)器吧。
執(zhí)行daphne django3.asgi:application
命令。(將其中的django3換成你的工程名字,在manage.py文件所在的路徑下執(zhí)行)
(venv) D:\work\for_test\django3>daphne django3.asgi:application 2019-12-04 10:20:07,637 INFO Starting server at tcp:port=8000:interface=127.0.0.1 2019-12-04 10:20:07,637 INFO HTTP/2 support not enabled (install the http2 and tls Twisted extras) 2019-12-04 10:20:07,637 INFO Configuring endpoint tcp:port=8000:interface=127.0.0.1 2019-12-04 10:20:07,637 INFO Listening on TCP address 127.0.0.1:8000
當(dāng)然,我們也是可以指定ip和port等參數(shù)的,詳細(xì)請(qǐng)學(xué)習(xí)daphne文檔https://pypi.org/project/daphne/
讀一下人家的啟動(dòng)信息:
- 默認(rèn)啟動(dòng)地址是127.0.0.1:8000
- 沒(méi)有開(kāi)啟HTTP/2的支持(需要安裝額外的包)
- 配置了端點(diǎn),開(kāi)始監(jiān)聽(tīng)端口
Nice,通過(guò)瀏覽器來(lái)訪問(wèn)一下吧!
依然是熟悉的白底火箭圖!圖片我就不貼了,看起來(lái)沒(méi)問(wèn)題。
可是,這是基于HTTP的同步通信,還不是異步請(qǐng)求!讓我們嘗試一下websocket吧!
四、嘗試Websocket
瀏覽器中按F12進(jìn)入‘坦克模式',再進(jìn)入console控制臺(tái),嘗試發(fā)送一個(gè)Websocket請(qǐng)求:
忽視前面的css問(wèn)題,重點(diǎn)在于這個(gè)ws請(qǐng)求,居然無(wú)法建立連接!返回狀態(tài)碼500,也就是服務(wù)器錯(cuò)誤!
再看看Pycharm后臺(tái)的信息:
127.0.0.1:5991 - - [04/Dec/2019:10:30:05] "WSCONNECTING /" - - 2019-12-04 10:30:05,246 ERROR Exception inside application: Django can only handle ASGI/HTTP connections, not websocket. File "d:\work\for_test\django3\venv\lib\site-packages\daphne\cli.py", line 30, in asgi await self.app(scope, receive, send) File "d:\work\for_test\django3\venv\lib\site-packages\django\core\handlers\asgi.py", line 146, in __call__ % scope['type'] Django can only handle ASGI/HTTP connections, not websocket. 127.0.0.1:5991 - - [04/Dec/2019:10:30:05] "WSDISCONNECT /" - -
重點(diǎn)在這句Django can only handle ASGI/HTTP connections, not websocket.
什么?Django不支持Websocket?說(shuō)好的ASGI,說(shuō)好的全雙工異步通信呢?
難道是我哪里搞錯(cuò)了?不行,我得看看源碼去!
五、Django3.0源碼
一路點(diǎn)點(diǎn)點(diǎn),翻了個(gè)遍,發(fā)現(xiàn)Django3.0與之前的2.2關(guān)于ASGI的區(qū)別就是多了下面兩個(gè)文件:
django.core.asgi
很簡(jiǎn)單,一看就懂,不多說(shuō):
import django from django.core.handlers.asgi import ASGIHandler def get_asgi_application(): django.setup(set_prefix=False) return ASGIHandler()
關(guān)鍵是django.core.handlers.asgi
這個(gè)文件,不到300行,總共就2個(gè)類(lèi),代碼就不貼了:
- ASGIRequest:繼承了HttpRequest類(lèi),一看就知道是構(gòu)造請(qǐng)求對(duì)象
- ASGIHandler:繼承了base.BaseHandler,這個(gè)就類(lèi)似WSGIHandler,用于具體處理ASGI請(qǐng)求
讓我們看看它的其中一段代碼:
# Serve only HTTP connections. # FIXME: Allow to override this. if scope['type'] != 'http': raise ValueError( 'Django can only handle ASGI/HTTP connections, not %s.' % scope['type'] )
這就是我們前面在瀏覽器中發(fā)送ws請(qǐng)求,但是無(wú)法建立連接的原因!
如果scope的type屬性不是http,那么彈出ValueError異常,并提示不支持該類(lèi)連接!
再看看人家寫(xiě)的注釋?zhuān)髅靼装椎膶?xiě)著Serve only HTTP connections. FIXME: Allow to override this.
。翻譯過(guò)來(lái)就是只支持HTTP連接,請(qǐng)自己重寫(xiě)這部分內(nèi)容修復(fù)這個(gè)缺陷。FIXME!FIXME!
好吧,我承認(rèn)白高興了一場(chǎng)。
六、總結(jié)
與Django3.0關(guān)于異步通信的初體驗(yàn)很不好,有下面幾點(diǎn)猜測(cè):
- 可能我水平不行,不會(huì)用Django
- 可能不是通過(guò)Websocket,而是別的手段與ASGI通信
- Django真的目前只提供了個(gè)接口,內(nèi)部實(shí)現(xiàn)還沒(méi)做
由于相關(guān)資料太少,多方查找,據(jù)說(shuō):
- Django會(huì)在后續(xù)的版本陸續(xù)實(shí)現(xiàn)完整的原生的異步通信能力,從同步機(jī)制切換到可兼容的異步機(jī)制
- 目前3.0階段,要與websocket通信依然得通過(guò)django-channel庫(kù),還不是原生支持
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
- 淺談django channels 路由誤導(dǎo)
- 詳解Django-channels 實(shí)現(xiàn)WebSocket實(shí)例
- Django使用Channels實(shí)現(xiàn)WebSocket的方法
- Django Channels 實(shí)現(xiàn)點(diǎn)對(duì)點(diǎn)實(shí)時(shí)聊天和消息推送功能
- django使用channels2.x實(shí)現(xiàn)實(shí)時(shí)通訊
- Django+uni-app實(shí)現(xiàn)數(shù)據(jù)通信中的請(qǐng)求跨域的示例代碼
- Django實(shí)現(xiàn)隨機(jī)圖形驗(yàn)證碼的示例
- django使用channels實(shí)現(xiàn)通信的示例
相關(guān)文章
python 實(shí)現(xiàn)定時(shí)任務(wù)的四種方式
這篇文章主要介紹了python 實(shí)現(xiàn)定時(shí)任務(wù)的四種方式,幫助大家更好的理解和學(xué)習(xí)使用python,感興趣的朋友可以了解下2021-04-04簡(jiǎn)單介紹Python的Tornado框架中的協(xié)程異步實(shí)現(xiàn)原理
這篇文章主要介紹了簡(jiǎn)單介紹Python的Tornado框架中的協(xié)程異步實(shí)現(xiàn)原理,作者基于Python的生成器講述了Tornado異步的特點(diǎn),需要的朋友可以參考下2015-04-04python django事務(wù)transaction源碼分析詳解
這篇文章主要介紹了python django事務(wù)transaction源碼分析詳解的相關(guān)資料,需要的朋友可以參考下2017-03-03Python之多線程爬蟲(chóng)抓取網(wǎng)頁(yè)圖片的示例代碼
本篇文章主要介紹了Python之多線程爬蟲(chóng)抓取網(wǎng)頁(yè)圖片的示例代碼,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2018-01-01Python全棧之進(jìn)程和守護(hù)進(jìn)程
這篇文章主要為大家介紹了Python進(jìn)程和守護(hù)進(jìn)程,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來(lái)幫助2021-12-12python中的os.mkdir和os.makedirs的使用區(qū)別及如何查看某個(gè)模塊中的某些字母開(kāi)頭的屬性方法
這篇文章主要介紹了python中的os.mkdir和os.makedirs的使用區(qū)別及如何查看某個(gè)模塊中的某些字母開(kāi)頭的屬性方法,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2023-03-03Python利用3D引擎寫(xiě)一個(gè)Pong游戲
之前,我們嘗試過(guò)用pygame做了一個(gè)2D的Pong游戲。本文將利用強(qiáng)大的3D引擎Ursina制作一個(gè)3D版的Pong游戲。文中的示例代碼講解詳細(xì),感興趣的可以了解一下2023-01-01