欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Python優(yōu)秀開(kāi)源項(xiàng)目Rich源碼解析的流程分析

 更新時(shí)間:2020年07月06日 11:32:16   作者:渡碼  
這篇文章主要介紹了Python優(yōu)秀開(kāi)源項(xiàng)目Rich源碼解析,本文通過(guò)實(shí)例圖文相結(jié)合給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下

這篇文章對(duì)優(yōu)秀的開(kāi)源項(xiàng)目Rich的源碼進(jìn)行解析,OMG,盤他。為什么建議閱讀源碼,有兩個(gè)原因,第一,單純學(xué)語(yǔ)言很難在實(shí)踐中靈活應(yīng)用,通過(guò)閱讀源碼可以看到每個(gè)知識(shí)點(diǎn)的運(yùn)用場(chǎng)景,印象會(huì)更深,以后寫代碼的時(shí)候就能應(yīng)用起來(lái);第二,通過(guò)閱讀優(yōu)秀的開(kāi)源代碼,可以學(xué)習(xí)比人的代碼規(guī)范、設(shè)計(jì)思路;第三,參與到開(kāi)源社區(qū),獲得更廣闊的的發(fā)展前景;第四,面試加分項(xiàng)。所以,有時(shí)間的話還是建議大家多讀讀優(yōu)秀開(kāi)源項(xiàng)目的源碼。

下面進(jìn)入今天的主題,這個(gè)開(kāi)源項(xiàng)目的名字叫Rich,地址:https://github.com/willmcgugan/rich 。這個(gè)項(xiàng)目是個(gè)英國(guó)老鐵開(kāi)發(fā)的,比較友好的是有中文文檔。它的作用是可以在控制臺(tái)輸出富文本和精美的可視化格式(如:表格、進(jìn)度條和markdown)。截圖感受一下

各種格式

進(jìn)度條

效果看起來(lái)很酷炫,我忍不住看了一些代碼,發(fā)現(xiàn)作者用的是Python 3.8版本實(shí)現(xiàn)的,好多新特性我也不了解,所以在看源碼過(guò)程中還補(bǔ)了一下語(yǔ)法基礎(chǔ)。下面以一個(gè)例子來(lái)簡(jiǎn)單看看Rich的源碼,源碼的講解我盡量言簡(jiǎn)意賅,重點(diǎn)講解源碼中涉及的一些關(guān)鍵的知識(shí)點(diǎn)。

先撿個(gè)軟柿子捏,如下:

from rich import print

print('Hello, [bold yellow]World[/bold yellow]!')

 

輸出效果:

可以看到對(duì)單詞World顯示為粗體、紅顏色。

先通過(guò)一張圖來(lái)看看大致流程

簡(jiǎn)單來(lái)說(shuō)就是將文本的格式轉(zhuǎn)化成標(biāo)準(zhǔn)輸出能夠識(shí)別的格式,然后輸出即可。下面來(lái)講解源碼,當(dāng)我們調(diào)用print函數(shù)時(shí),最終程序會(huì)跳轉(zhuǎn)到console.py文件的print函數(shù)中,執(zhí)行以下代碼

調(diào)用self._collect_renderables函數(shù)處理輸入的字符串,將需要格式化的部分標(biāo)出來(lái),返回的renderables變量是一個(gè)Text列表,因?yàn)檩斎胫挥?個(gè)字符串,所以列表的大小為1,變量結(jié)果如下

Span(7, 12, 'bold red')便是框出來(lái)需要格式化的內(nèi)容。

上述代碼還有一個(gè)with self,它的作用我們一會(huì)兒再說(shuō)。接著print函數(shù)往下看

這里會(huì)遍歷剛剛提到的renderables變量,先調(diào)用render函數(shù)渲染輸入的文本,然后調(diào)用extend函數(shù)將render返回的結(jié)果添加到self._buffer列表里。這里有幾個(gè)知識(shí)點(diǎn)簡(jiǎn)單說(shuō)一下

  • self._buffer是函數(shù)調(diào)用,由于它加了@property注解,所以調(diào)用是可以不用加小括號(hào),它返回的是self._thread_locals.buffer變量,該變量是List[Segment]類型的
  • self._thread_locals.buffer變量用到dataclasses模塊的field函數(shù)初始化,初始化代碼為buffer: List[Segment] = field(default_factory=list)dataclassesPython 3.7 版本的新引入的模塊,field函數(shù)可提供更加靈活的初始化方式,并且該模塊中的@dataclass注解可以為類自動(dòng)添加__init__等方法,比較方便
  • extend = self._buffer.extend這種寫法將listextent函數(shù)存到了臨時(shí)變量里,后續(xù)直接通過(guò)extend調(diào)用該函數(shù),比對(duì)象名.extend的方式更簡(jiǎn)潔。

下面我們來(lái)看render(renderable, render_options)函數(shù)的渲染邏輯,該函數(shù)里會(huì)調(diào)用下面的代碼

render_iterable = renderable.__rich_console__(self, options)

在函數(shù)聲明里renderable對(duì)象是RenderableType類型的,但實(shí)際上Text類型的,并且這兩種類型沒(méi)有繼承關(guān)系,這里沒(méi)太想明白作者為什么這樣搞。所以,這里的__rich_console__函數(shù)我們要到text.py文件中去找。__rich_console__函數(shù)最終會(huì)調(diào)用Text對(duì)象的render函數(shù),核心代碼如下:

def render(self, console: "Console", end: str = "") -> Iterable["Segment"]:
 style_map = {index: get_style(span.style) for index, span in enumerated_spans}

 _Segment = Segment

 for (offset, leaving, style_id), (next_offset, _, _) in zip(spans, spans[1:]):
 yield _Segment(text[offset:next_offset], get_current_style())

調(diào)用get_style函數(shù),將格式轉(zhuǎn)為Style對(duì)象,如:'bold red'轉(zhuǎn)成Style對(duì)象,然后按照不同的顯示格式進(jìn)行‘分片',每個(gè)‘片段'構(gòu)造一個(gè)Segment對(duì)象存儲(chǔ)文本及其對(duì)應(yīng)的格式。

get_style函數(shù)會(huì)調(diào)用Style.parse(name)生成Style對(duì)象,核心代碼如下

@lru_cache(maxsize=1024)
def parse(cls, style_definition: str) -> "Style":
 words = iter(style_definition.split())
 for original_word in words:
 word = original_word.lower()
 if word == "on":
 # ...省略
 elif word in style_attributes:
 attributes[style_attributes[word]] = True
 else:
 color = word
 style = Style(color=color, bgcolor=bgcolor, link=link, **attributes)
 return style

參數(shù)style_definition取值為bold red,分割后生成['bold', 'red']列表,當(dāng)word變量等于'bold'時(shí),會(huì)執(zhí)行attributes[style_attributes[word]] = True語(yǔ)句,執(zhí)行后attributes等于{'bold': true},它是一個(gè)字典。當(dāng)word變量等于red時(shí),執(zhí)行color=word語(yǔ)句。最終調(diào)用導(dǎo)數(shù)第二行構(gòu)造Style對(duì)象,Style對(duì)象最核心的兩個(gè)數(shù)據(jù)形式_attributes_color, 前者是int類型,在我們例子中取值是1,代表'bold',即:粗體。后者代表顏色,即:'red',它是Color類型的,該類中有個(gè)屬性number也是我們后續(xù)要用到的。

下面來(lái)看下__rich_console__函數(shù)返回了哪些Segment對(duì)象

可以看到有4個(gè),每一個(gè)都有文本及其Style對(duì)象。

回到render(renderable, render_options)函數(shù),剛剛介紹了__rich_console__部分,下面還有返回的代碼, 一起來(lái)看看

iter_render = iter(render_iterable)
for render_output in iter_render:
 if isinstance(render_output, Segment):
 yield render_output

render_iterable變量是__rich_console__的返回值,即:4個(gè)Segment對(duì)象。遍歷后通過(guò)yield方式返回。該關(guān)鍵字用來(lái)返回一個(gè)迭代器,也可以理解為一個(gè)列表。并且yield返回有個(gè)特點(diǎn),函數(shù)返回值只有真正被使用的時(shí)候才會(huì)執(zhí)行調(diào)用函數(shù)。

這樣,render(renderable, render_options)函數(shù)就講解完了,返回上一層extend(render(renderable, render_options)),通過(guò)extend函數(shù)將4個(gè)Segment對(duì)象保存到buffer中,結(jié)果如下

然后print方法就執(zhí)行完了??雌饋?lái)已經(jīng)結(jié)束了,然而控制臺(tái)打印的代碼貌似沒(méi)有看到。答案就在剛剛的with self中,with關(guān)鍵字使得執(zhí)行完代碼體后,會(huì)自動(dòng)調(diào)用self__exit__函數(shù)。__exit__函數(shù)中調(diào)用_render_buffer函數(shù)進(jìn)行最終的輸出,核心代碼如下

output: List[str] = []
append = output.append
for line in Segment.split_and_crop_lines(buffer, self.width, pad=False):
 for text, style, is_control in line:
 if style and not is_control:
  append(
  style.render(
   text,
   color_system=color_system,
   legacy_windows=legacy_windows,
  )
  )
rendered = "".join(output)

return rendered

split_and_crop_lines函數(shù)是為了適應(yīng)控制臺(tái)的寬度,暫時(shí)忽略它。line變量仍然是剛剛提到的4個(gè)Segment對(duì)象,通過(guò)for text, style, is_control in line直接將每個(gè)Segment對(duì)象的屬性解出來(lái)并賦給text, style, is_control變量,最終每個(gè)style對(duì)象都會(huì)調(diào)用render方法完成最后的渲染。

render方法核心代碼如下

attrs = self._make_ansi_codes(color_system)
rendered = f"\x1b[{attrs}m{text}\x1b[0m" if attrs else text

_make_ansi_codes函數(shù)就不展開(kāi)了, 其實(shí)就是利用上面提到的_attributesnumber屬性生成標(biāo)準(zhǔn)輸出的能夠識(shí)別的格式,返回值attrs的結(jié)果為1;31,1取自_attributes代表粗體,31中的1取自number代表顏色,其他顏色取值是不同的,比如黃色是33,紫色是35。最后通過(guò)f-string格式(新特性)生成rendered變量,取值為World它就是標(biāo)準(zhǔn)輸出流能夠識(shí)別的格式。

回到_render_buffer函數(shù)中,調(diào)用rendered = "".join(output)將4個(gè)渲染后的片段拼在一起,返回。返回后執(zhí)行的代碼如下:

text = self._render_buffer()
if text:
 self.file.write(text)

self.file變量的賦值語(yǔ)句為self.file = file or sys.stdout,由于我們沒(méi)有定義file變量,所以self.file取值為sys.stdout。最終的輸出為sys.stdout.write(text),至此整個(gè)流程就講解完了。如果你理解了上述邏輯,應(yīng)該可以通過(guò)下面代碼輸出同樣的效果

sys.stdout.write('Hello, \033[1;31mWorld\033[0m!')

所以Rich做的就是把文字格式準(zhǔn)成標(biāo)準(zhǔn)輸出流能識(shí)別的格式。

Rich里用到的代碼確實(shí)挺新的,能學(xué)到很多東西,比直接看書(shū)來(lái)的快,有興趣的朋友可以自行閱讀。

源碼:https://github.com/willmcgugan/rich

總結(jié)

到此這篇關(guān)于Python優(yōu)秀開(kāi)源項(xiàng)目Rich源碼解析的文章就介紹到這了,更多相關(guān)Python優(yōu)秀開(kāi)源項(xiàng)目?jī)?nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • 深入探究Python Numba庫(kù)編譯優(yōu)化利器

    深入探究Python Numba庫(kù)編譯優(yōu)化利器

    這篇文章主要為大家介紹了Python Numba庫(kù)編譯優(yōu)化利器深入探究,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2024-01-01
  • Python多版本安裝與Jupyter Lab使用方式

    Python多版本安裝與Jupyter Lab使用方式

    這篇文章主要介紹了Python多版本安裝與Jupyter Lab使用方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2024-01-01
  • python開(kāi)發(fā)的自動(dòng)化運(yùn)維工具ansible詳解

    python開(kāi)發(fā)的自動(dòng)化運(yùn)維工具ansible詳解

    ansible是新出現(xiàn)的自動(dòng)化運(yùn)維工具,基于Python開(kāi)發(fā),集合了眾多運(yùn)維工具(puppet、chef、func、fabric)的優(yōu)點(diǎn),實(shí)現(xiàn)了批量系統(tǒng)配置、批量程序部署、批量運(yùn)行命令等功能,這篇文章主要介紹了python開(kāi)發(fā)的自動(dòng)化運(yùn)維工具ansible詳解,需要的朋友可以參考下
    2021-08-08
  • 100?個(gè)?Python?小例子(練習(xí)題四)

    100?個(gè)?Python?小例子(練習(xí)題四)

    這篇文章主要給大家分享100?個(gè)?Python?小例子,前文分享了一二三,本文的四十最后一篇了,這篇就把100道python小練習(xí)全分享完了,感興趣的小伙伴也可以去練習(xí)前幾期內(nèi)容,洗碗給這幾篇文章給你的學(xué)習(xí)帶來(lái)幫助
    2022-01-01
  • python 5個(gè)頂級(jí)異步框架推薦

    python 5個(gè)頂級(jí)異步框架推薦

    這篇文章主要介紹了python5個(gè)頂級(jí)的異步框架,幫助大家更好的利用python進(jìn)行web開(kāi)發(fā),感興趣的朋友可以了解下
    2020-09-09
  • 使用Python實(shí)現(xiàn)在Word中添加或刪除超鏈接

    使用Python實(shí)現(xiàn)在Word中添加或刪除超鏈接

    在Word文檔中,超鏈接是一種將文本或圖像連接到其他文檔、網(wǎng)頁(yè)或同一文檔中不同部分的功能,本文將為大家介紹一下Python如何實(shí)現(xiàn)在Word中添加或刪除超鏈接,需要的可以參考下
    2025-01-01
  • 如何基于python實(shí)現(xiàn)單目三維重建詳解

    如何基于python實(shí)現(xiàn)單目三維重建詳解

    單目三維重建是根據(jù)單個(gè)攝像頭的運(yùn)動(dòng)模擬雙目視覺(jué)獲得物體在空間中的三維視覺(jué)信息,下面這篇文章主要給大家介紹了關(guān)于如何基于python實(shí)現(xiàn)單目三維重建的相關(guān)資料,文中通過(guò)實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2022-06-06
  • Python代碼模擬CPU工作原理

    Python代碼模擬CPU工作原理

    Python代碼來(lái)實(shí)現(xiàn)一個(gè)最簡(jiǎn)單的CPU。用代碼模擬大的部件,使大家從原理上理解CPU工作。使它可編程,支持加減法運(yùn)算、讀寫內(nèi)存、無(wú)條件跳轉(zhuǎn)、條件跳轉(zhuǎn)的功能。
    2023-01-01
  • Django對(duì)數(shù)據(jù)庫(kù)進(jìn)行添加與更新的例子

    Django對(duì)數(shù)據(jù)庫(kù)進(jìn)行添加與更新的例子

    今天小編就為大家分享一篇Django對(duì)數(shù)據(jù)庫(kù)進(jìn)行添加與更新的例子,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2019-07-07
  • python使用opencv驅(qū)動(dòng)攝像頭的方法

    python使用opencv驅(qū)動(dòng)攝像頭的方法

    今天小編就為大家分享一篇python使用opencv驅(qū)動(dòng)攝像頭的方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2018-08-08

最新評(píng)論