<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          國(guó)人開(kāi)源的異步 Python ORM:GINO

          共 10423字,需瀏覽 21分鐘

           ·

          2021-09-28 12:01

          來(lái)源:GINO 官方文檔
          https://python-gino.org/docs/zh/master/tutorials/announcement.html


          隨著 Tornado[1] 和 asyncio[2] 等框架的陸續(xù)涌現(xiàn),Python 異步編程這個(gè)話題也在逐漸升溫。在這個(gè)燒腦的異步世界里,有沒(méi)有辦法可以既方便快捷、又簡(jiǎn)單明了地訪問(wèn)數(shù)據(jù)庫(kù)呢?GitHub 千星項(xiàng)目 GINO 了解一下!



          1. GINO 是誰(shuí)


          GINO 是一個(gè)“輕量級(jí)”異步 ORM 框架,它的全稱是 GINO Is Not ORM,借鑒了 GNU is Not Unix 的遞歸定義[3] 手法。所以,GINO 一定要全!部!大!寫(xiě)!如果像這樣“Gino”就變成了人名,你肯定要問(wèn)一句“這是誰(shuí)”。


          ORM,即關(guān)系對(duì)象映射(Object-Relational Mapping[4]),是一類開(kāi)發(fā)人員喜聞樂(lè)見(jiàn)的效率工具,它們"極大地"提升了寫(xiě)代碼的幸福指數(shù)。GINO 是用來(lái)訪問(wèn)數(shù)據(jù)庫(kù)的,也提供了對(duì)象映射的工具,那為什么非說(shuō) GINO 不是 ORM 呢?


          因?yàn)槲飿O必反,ORM 在帶來(lái)生活便利的同時(shí),也是 bug 生長(zhǎng)的溫床 —— 傳統(tǒng) ORM 往往會(huì)選擇犧牲明確性(explicitness)來(lái)?yè)Q取便捷性(convenience),再加上 Python 得天獨(dú)厚的靈活性(flexibility),創(chuàng)造出了一種爆炸式的化學(xué)反應(yīng)。一旦代碼初具規(guī)模,項(xiàng)目或多或少都會(huì)遇到 ORM 反噬的情景:性能莫名其妙的差、出問(wèn)題找不到原因、為了雞毛蒜皮的小事大動(dòng)干戈。隨便一句 current_user.name 都有可能觸發(fā)一大堆意想不到的數(shù)據(jù)庫(kù)調(diào)用,這代碼你讓我怎么調(diào)試?


          傳統(tǒng) ORM 的學(xué)習(xí)曲線前平后陡,能在快速原型開(kāi)發(fā)中大展身手,但應(yīng)用到大型項(xiàng)目中卻十分考驗(yàn)開(kāi)發(fā)人員的平均水平。


          所有這些問(wèn)題如果再放進(jìn)異步編程的環(huán)境里,那就是 O(n2) 的復(fù)雜度了 —— 哦不,是 O(2n)。這對(duì)于一款優(yōu)秀的異步 ORM 框架來(lái)說(shuō)是不可接受的,所以 GINO 是 ORM 但不是一個(gè)傳統(tǒng)的 ORM,正猶如 GNU 不是一個(gè)傳統(tǒng)的 Unix 一樣,形似而神不似。


          所以在 2017 年創(chuàng)作之初,我就給 GINO 定下了兩個(gè)業(yè)績(jī)目標(biāo):1) 方便快捷,2) 簡(jiǎn)單明了。三年后的今天,我索性在 1.0 穩(wěn)定版發(fā)布的前夕做個(gè)年終總結(jié)。


          2. 先說(shuō)"方便快捷"

          "方便快捷"主要說(shuō)的是開(kāi)發(fā)效率。


          重視開(kāi)發(fā)效率的概念對(duì)于寫(xiě) Python 的同學(xué)來(lái)說(shuō)可能并不陌生,某些場(chǎng)景下,開(kāi)發(fā)人員的時(shí)間確實(shí)比機(jī)器的時(shí)間值錢。所以,傳統(tǒng) ORM 里的對(duì)象映射不能丟。


          from gino import Ginodb = Gino()class User(db.Model):    __tablename__ = "users"    id = db.Column(db.Integer, primary_key=True)    name = db.Column(db.String)

          這么定義表結(jié)構(gòu)甚至讓人有點(diǎn)小興奮。咦,為什么這么眼熟?


          沒(méi)有錯(cuò),這就是 SQLAlchemy ORM[5] 的定義風(fēng)格。GINO 并不是從頭造輪子,而是在 SQLAlchemy core[6](SQLAlchemy 中負(fù)責(zé)構(gòu)建 SQL 的底層核心)的基礎(chǔ)上開(kāi)發(fā)的。這么做除了能保持熟悉的味道(以節(jié)省學(xué)習(xí)和遷移成本),更重要的是帶來(lái)了整個(gè) SQLAlchemy 的生態(tài)環(huán)境:開(kāi)箱即用的數(shù)據(jù)庫(kù)變更管理工具 Alembic[7]、各種 SQLAlchemy 的增強(qiáng)插件[8]、專業(yè)領(lǐng)域的 PostGIS/geoalchemy[9] 等,GINO 全都兼容。


          是不是十分方便、十分快捷?不止這樣。


          GINO 一站式地解決了常用 CRUD 快捷方式[10]、上下文管理(aiocontextvars[11][12])、數(shù)據(jù)庫(kù)事務(wù)封裝和嵌套[13]、連接池管理和懶加載[14] 等多項(xiàng)便捷功能,無(wú)額外依賴關(guān)系,即裝即用。


          daisy = await User.create(name="daisy")await daisy.update(name="Daisy").apply()

          GINO 還提供了[15] 各大流行異步 Web 框架的定制版插件,能叫上名字的像 Tornado[1]、aiohttp[16]、Sanic[17]、FastAPI[18]/Starlette[19]、Quart[20] 什么的都有,從簡(jiǎn)單示范到生產(chǎn)環(huán)境的各種例子品種齊全,媽媽再也不用擔(dān)心我不會(huì)集成 Web 框架了。


          為了讓不同應(yīng)用場(chǎng)景下的用戶體驗(yàn)到最大的善意,GINO 目前支持三種不同程度的用法,成功實(shí)現(xiàn)了對(duì)同期競(jìng)品 asyncpgsa[21] 的降維打擊:

          1. 最少侵入型[22]:SQLAlchemy core 原教旨主義者,只有異步執(zhí)行時(shí)才用到 GINO。

          2. 終身不婚型[23]:天生厭惡"對(duì)象",只愿定義"表",空手接 SQL。

          3. 火力全開(kāi)型[24]:最大程度的便利,非典型異步 ORM。


          最后,雖然是 Python(絕不是黑哈),但 GINO 在執(zhí)行效率上也沒(méi)落下。基于 MagicStack 出品必屬精品的、一秒可讀百萬(wàn)行的 asyncpg[25],以及 uvloop[26](可選)的強(qiáng)力加持,GINO 跑起來(lái)也是可以飛快的,被廣泛應(yīng)用于諸如實(shí)時(shí)匯率、聊天機(jī)器人、在線游戲等高并發(fā)領(lǐng)域,深受俄羅斯和烏克蘭人民的愛(ài)戴。


          3. 再說(shuō)"簡(jiǎn)單明了"

          Explicit is better than implicit.

          Simple is better than complex.

          -- The Zen of Python, PEP 20[27]


          Python 之禪完美表達(dá)了 GINO 的立場(chǎng) —— 明確性(explicitness)對(duì)于上了規(guī)模的異步工程項(xiàng)目來(lái)說(shuō)尤為重要,因此 GINO 的很多設(shè)計(jì)都受到了明確性的影響。


          比如說(shuō),GINO 的 Model 是完全無(wú)狀態(tài)的普通 Python 對(duì)象(POPO[28])—— 例如前面的 User 類,它的實(shí)例

          daisy 就是內(nèi)存里面的常規(guī)對(duì)象,你可以用 daisy.name 訪問(wèn)屬性,也可以用 daisy.name = "DAISY" 來(lái)修改屬性,或者用 u = User() 來(lái)創(chuàng)建新的實(shí)例,這些操作都不會(huì)訪問(wèn)數(shù)據(jù)庫(kù),絕對(duì)綠色環(huán)保無(wú)毒副作用。


          等到需要操作數(shù)據(jù)庫(kù)的時(shí)候,你一定會(huì)有感知的。比如執(zhí)行 INSERT 要用 u = await User.create(),而 UPDATE 則是 await u.update(name="Daisy").apply()。

          其中, u.update(name="Daisy") 與 u.name = "Daisy" 類似,都是只在內(nèi)存里修改對(duì)象的屬性,不同的是 u.update() 還會(huì)返回一個(gè)包含本次變更的中間結(jié)果,對(duì)其執(zhí)行 await xxx.apply() 則會(huì)將這些變更應(yīng)用到數(shù)據(jù)庫(kù)里。

          這里的 await 就是明確性的關(guān)鍵,意味著我們要跳出去執(zhí)行數(shù)據(jù)庫(kù)操作了。換句話說(shuō),沒(méi)有 await 就沒(méi)有數(shù)據(jù)庫(kù)操作。


          另一方面,對(duì)于如何將數(shù)據(jù)庫(kù)查詢結(jié)果組裝成內(nèi)存對(duì)象及其屬性,GINO 也有一套精妙的顯式機(jī)制 —— 可定制化的加載器 loaders[29]。對(duì)于簡(jiǎn)單直觀的一對(duì)一加載,GINO 自然是伺候到家的,比如用 u = await User.get(1) 可以直接獲取到 ID 為 1 的用戶對(duì)象。但是對(duì)于更復(fù)雜的查詢,GINO 不會(huì)去無(wú)端猜測(cè)主人的意圖,而全權(quán)交給用戶來(lái)明確地定義。加載器的用法也是很簡(jiǎn)單的,比如一個(gè)用戶可能寫(xiě)了很多本書(shū):


          class Book(db.Model):    __tablename__ = "books"    id = db.Column(db.Integer, primary_key=True)    title = db.Column(db.String)    author_id = db.ForeignKey("users.id")

          然后這樣來(lái)加載這種多對(duì)一關(guān)系,以同時(shí)獲取所有的書(shū)和他們的作者:


          query = Book.outerjoin(User).select()loader = Book.load(author=User)async for book in query.gino.load(loader).iterate():    print(book.title, "written by", book.author.name)

          很簡(jiǎn)單的一個(gè)外連接查詢 Book.outerjoin(User),配合一個(gè)直觀的加載器 Book.load(author=User),就實(shí)現(xiàn)了:

          1. 執(zhí)行 SELECT * FROM books LEFT JOIN users ON ...;

          2. 將數(shù)據(jù)庫(kù)返回結(jié)果的每一行中,屬于 books 的字段加載成一個(gè) Book 實(shí)例;

          3. 然后將該行中剩下的屬于 users 的字段加載成一個(gè) User 實(shí)例;

          4. 最后將 User 實(shí)例設(shè)置到 Book 實(shí)例的 author 屬性上。


          既簡(jiǎn)單又明了有沒(méi)有!你甚至可以手寫(xiě)任何 SQL,然后定制加載器自動(dòng)加載成期望的對(duì)象關(guān)系,精準(zhǔn)控制加載行為,指哪兒打哪兒。GINO 還有很多類似的特性,在這里就不一一列舉了。


          4. 優(yōu)勢(shì)與不足


          隨著這幾年 GINO 不斷演進(jìn)成熟,Python 開(kāi)源社區(qū)里也相繼出現(xiàn)了像 Tortoise ORM[30]、ORM[31](是的,這個(gè)項(xiàng)目就叫 ORM......我真 ORZ。出品方是 Encode,Starlette 就是他們的作品)等優(yōu)秀的異步 ORM 框架。它們關(guān)注的重點(diǎn)與 GINO 稍有不同,但都是同行就不多評(píng)價(jià)了。


          GINO 的最大優(yōu)勢(shì)還是在于充分平衡了開(kāi)發(fā)效率和明確性之間的辯證矛盾關(guān)系,用 GINO 開(kāi)發(fā)應(yīng)用程序的時(shí)候不用擔(dān)心會(huì)被意料之外的行為所驚嚇到,同時(shí)也不需要為這種明確性付出過(guò)大的工程代價(jià),上手后依然可以快速、快樂(lè)地編程。同時(shí),大量的成功案例也證明了 GINO 已經(jīng)初步具備發(fā)布 1.0 穩(wěn)定版的各種條件,可以謹(jǐn)慎地用于生產(chǎn)環(huán)境了。


          以下是近來(lái)統(tǒng)計(jì)到的關(guān)于 GINO 的應(yīng)用案例:

          • 筆者工作上開(kāi)發(fā)的一個(gè)服務(wù):https://github.com/uc-cdis/metadata-service

          • 還是筆者自己寫(xiě)的一個(gè)工具:https://github.com/fantix/aintq

          • 一個(gè)匯率 API 服務(wù):https://exchangeratesapi.io/


          • 各種 Telegram、Discord 的 Bot。

          • ArchLinux 用戶包:https://aur.archlinux.org/packages/python-gino/

          • https://github.com/bryanforbes/gino-stubs/

          • 俄語(yǔ)教程:https://www.youtube.com/watch?v=WW4rOnfhiQY

          • 高性能模板項(xiàng)目:https://github.com/leosussan/fastapi-gino-arq-uvicorn

          • 還有幾個(gè)商用的,但沒(méi)征得同意就不貼出來(lái)了。


          另外,GINO 還貼心地提供了中文文檔[32],從上手教程到原理說(shuō)明應(yīng)有盡有(雖然文檔還在努力編寫(xiě)中!):

          GINO 目前的不足之處還有一些,比如沒(méi)有照顧到 Python 3 的類型提示,因此還不能完全發(fā)揮 IDE 的潛能(上面那個(gè) gino-stubs 就是有人受不了了自己寫(xiě)了一個(gè)類型注解)。MySQL 目前也是不支持的,但 GINO 從比較早就解耦了不同 SQL 方言和驅(qū)動(dòng)的集成,所以這些功能會(huì)陸續(xù)在 1.1 和 1.2 版本中跟上。


          5. 建設(shè)社會(huì)主義


          GINO 是一個(gè)開(kāi)源項(xiàng)目,所以歡迎大家一起來(lái)建設(shè)!


          目前急需幫助的有:

          1. 各個(gè) Web 框架插件的維護(hù)工作需要多人認(rèn)領(lǐng);

          2. 更多的例子和文檔,以及中文、俄文的翻譯;

          3. MySQL 的支持。


          以及下面這些一直需要的幫助:

          1. 用 GINO,找 bug,提建議;

          2. 修 bug,做功能,提 PR;

          3. 維護(hù)社區(qū),回答問(wèn)題,參與討論;

          4. 最后也是最重要的:去 GitHub 上給 GINO 加一顆星星!

          6. 關(guān)于作者

          I'm a software architect, fan of coding for over 20 years, and now focusing on software engineering, high concurrency and development performance. Python is my chief language, and I worked on Linux for 10 years, managing development teams up to 20 people for 8 years. Big fan of open source, created project GINO with 1000+ GitHub stars.


          OPEN SOURCE

          Python / 2018-2019

          I started to contribute to Python programming language with MagicStack fellows, focusing on the asyncio library.

          GINO / 2017-2019

          GINO is an ORM library for Python asyncio. It is an integration of SQLAlchemy core and asyncpg.

          aioh2 / 2016

          This is an integration of an HTTP/2 protocol library and Python 3 asyncio.

          tulipcore / 2015

          I've implemented the most part of the event loop core of Gevent with pure Python 3 asyncio (tulip) code.

          zmq.rs / 2014

          It was my attempt to implement the ZeroMQ stack in pure Rust.

          ArchLinux / 2013 - 2016

          I maintained the packages of a dozen of build toolchains and base libraries of ArchLinux for x32-ABI, e.g. GCC, glibc, openssl, curl, util-linux, etc.

          Gevent / 2011 - 2013

          I contributed the initial port of Gevent to Python 3, which was later merged into Gevent 1.1 by its new maintainer. I've also ported Greenlet to x32-ABI.

          Translations / 2008 - 2015

          I was involved/started several translation projects, e.g. Ubuntu, libexif, Twisted, Python-beginners, ZeroMQ, etc.


          87 年生人,6 歲開(kāi)始接觸編程,二十五六年的編程史和十三四年的工作經(jīng)驗(yàn)教會(huì)了我許多軟件開(kāi)發(fā)的奧義。小時(shí)候?qū)?GBasic、QBasic 和 Visual Basic;大學(xué)里開(kāi)始寫(xiě) Java 并接觸到了 FreeBSD 和 Ubuntu 等開(kāi)源項(xiàng)目且一發(fā)不可收拾;工作頭五年轉(zhuǎn)向了 Python,通過(guò) Twisted 和 Eventlet 等項(xiàng)目了解了異步編程,期間貢獻(xiàn)了 Gevent 的 Python 3 遷移;也曾在創(chuàng)業(yè)的潮流中留下身影,親身經(jīng)歷并見(jiàn)證了軟件技術(shù)隨著手游、新媒體、礦圈、互金、電商、社交、文娛、汽車等行業(yè)的起起伏伏;目前在芝大繼續(xù)做生物大數(shù)據(jù)相關(guān)的開(kāi)源項(xiàng)目。業(yè)余時(shí)間除了開(kāi)發(fā)維護(hù) GINO 項(xiàng)目外,還會(huì)偶爾修一修 uvloop、asyncpg 和 CPython 的 bug :P

          7. 參考文獻(xiàn)

          [1] Facebook. Tornado.

          URL: https://zh.wikipedia.org/wiki/Tornado.

          [2] Python Software Foundation. asyncio — 異步 I/O.

          URL: https://docs.python.org/zh-cn/3/library/asyncio.html.

          [3] 維基百科. GNU.

          URL: https://zh.wikipedia.org/wiki/GNU.

          [4] 維基百科. 對(duì)象關(guān)系映射.

          URL: https://zh.wikipedia.org/wiki/對(duì)象關(guān)系映射

          [5] 維基百科. SQLAlchemy.

          URL: https://zh.wikipedia.org/wiki/SQLAlchemy.

          [6] Michael Bayer. SQLAlchemy Core - SQLAlchemy . Documentation.

          URL: https://docs.sqlalchemy.org/en/13/core/index.html.

          [7] Michael Bayer. Welcome to Alembic’s documentation!

          URL: https://alembic.sqlalchemy.org/en/latest/.

          [8] Hong Minhee. A curated list of awesome tools for SQLAlchemy.

          URL: https://github.com/dahlia/awesome-sqlalchemy.

          [9] Does it have postgis support? Does it have postgis support?

          URL: https://github.com/python-gino/gino/issues/627.

          [10] Fantix King. GINO 基礎(chǔ)教程 - 增刪改查.

          URL: https://python-gino.org/docs/zh/master/tutorials/tutorial.html#crud-operations.

          [11] Python Software Foundation. contextvars —Context Variables.

          URL: https://docs.python.org/3/library/contextvars.html.

          [12] Fantix King. gino/aiocontextvars.py.

          URL: https://github.com/python-gino/gino/blob/f2c273a43a3ed893a767d4239046f2befabf510d/src/gino/aiocontextvars.py.

          [13] Fantix King. 數(shù)據(jù)庫(kù)事務(wù).

          URL: https://python-gino.org/docs/zh/master/how-to/transaction.html.

          [14] Fantix King. 引擎與連接.

          URL: https://python-gino.org/docs/zh/master/explanation/engine.html.

          [15] GINO Community. GINO Community.

          URL: https://github.com/python-gino/.

          [16] aiohttp maintainers. Welcome to AIOHTTP.

          URL: https://docs.aiohttp.org/en/stable/.

          [17] Sanic Community. Sanic Framework.

          URL: https://sanicframework.org/.

          [18] Sebastián Ramírez. FastAPI.

          URL: https://fastapi.tiangolo.com/.

          [19] Encode OSS. Starlette.

          URL: https://www.starlette.io/.

          [20] Philip Jones. Quart Documentation.

          URL: https://pgjones.gitlab.io/quart/.

          [21] Canopy. asyncpgsa - A wrapper around asyncpg for use with sqlalchemy.

          URL: https://github.com/CanopyTax/asyncpgsa.

          [22] Fantix King. 表結(jié)構(gòu)定義 - GINO 引擎.

          URL: https://pythongino.org/docs/zh/master/how-to/schema.html#gino-engine.

          [23] Fantix King. 表結(jié)構(gòu)定義 - GINO core.

          URL: https://python-gino.org/docs/zh/master/how-to/schema.html#gino-core.

          [24] Fantix King. 表結(jié)構(gòu)定義 - GINO ORM.

          URL: https://python-gino.org/docs/zh/master/how-to/schema.html#gino-orm.

          [25] MagicStack Inc. asyncpg - A fast PostgreSQL Database Client Library for Python/asyncio.

          URL: https://github.com/MagicStack/asyncpg.

          [26] MagicStack Inc. uvloop - Ultra fast asyncio event loop.

          URL: https://github.com/MagicStack/uvloop.

          [27] Tim Peters. PEP ? The Zen of Python.

          URL: https://www.python.org/dev/peps/pep-0020/.

          [28] Wikipedia. Plain old Java object.

          URL: https://en.wikipedia.org/wiki/Plain_old_Java_object.

          [29] Fantix King. 加載器與關(guān)系.

          URL: https://python-gino.org/docs/zh/master/how-to/loaders.html.

          [30] Andrey Bondar. Tortoise ORM.

          URL: https://tortoise.github.io/.

          [31] Encode OSS. ORM - An async ORM.

          URL: https://github.com/encode/orm.

          [32] Yury Selivanov. PEP ? Coroutines with async and await syntax.

          URL: https://www.python.org/dev/peps/pep-0492/. (Apr , ).

          - EOF -


          回復(fù)關(guān)鍵字“簡(jiǎn)明python ”,立即獲取入門必備書(shū)籍簡(jiǎn)明python教程》電子版

          回復(fù)關(guān)鍵字爬蟲(chóng)”,立即獲取爬蟲(chóng)學(xué)習(xí)資料

          點(diǎn)擊關(guān)注【python入門與進(jìn)階】,閱讀更多精彩內(nèi)容
          ??????

          推薦

          瀏覽 53
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  在线日韩在线 | 日韩三级在线播放 | 国产成人久久久 | 亚洲激情久久久久豆花 | 免费视频色情 |