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

          漲見識(shí)了,在終端執(zhí)行 Python 代碼的 6 種方式!

          共 4278字,需瀏覽 9分鐘

           ·

          2021-05-16 00:40


          原作:BRETT CANNON

          譯者:豌豆花下貓@Python貓

          英文:https://snarky.ca/the-many-ways-to-pass-code-to-python-from-the-terminal

          大家好,歡迎來到 Crossin的編程教室 !

          我們通常運(yùn)行程序都是通過IDE里執(zhí)行運(yùn)行,有時(shí)候也會(huì)在命令行通過類似

          python hello.py

          運(yùn)行代碼。實(shí)際上,在命令行中運(yùn)行python程序還有一些其他的方法。這些方法主要運(yùn)用在服務(wù)器環(huán)境上。今天給大家分享一篇文章,來聊一聊你平常可能不會(huì)知道的python執(zhí)行方式。


          為了我們推出的 VS CodePython 插件[1],我寫了一個(gè)簡(jiǎn)單的腳本來生成變更日志[2](類似于Towncrier[3],但簡(jiǎn)單些,支持 Markdown,符合我們的需求)。在發(fā)布過程中,有一個(gè)步驟是運(yùn)行python news,它會(huì)將 Python 指向我們代碼中的"news"目錄。

          前幾天,一位合作者問這是如何工作的,似乎我們團(tuán)隊(duì)中的每個(gè)人都知道如何使用-m?請(qǐng)參閱我的有關(guān)帶 -m 使用 pip 的文章[4],了解原因。

          這使我意識(shí)到其他人可能不知道有五花八門的方法可以將 Python 指向要執(zhí)行的代碼,因此有了這篇文章。

          1、通過標(biāo)準(zhǔn)輸入和管道

          因?yàn)槿绾斡霉艿纻鳀|西給一個(gè)進(jìn)程是屬于 shell 的內(nèi)容,我不打算深入解釋。毋庸置疑,你可以將代碼傳遞到 Python 中。

          # 管道傳內(nèi)容給 python
          echo "print('hi')" | python

          如果將文件重定向到 Python,這顯然也可以。

          # 重定向一個(gè)文件給 python
          python < spam.py

          歸功于 Python 的 UNIX 傳統(tǒng),這些都不太令人感到意外。

          2、通過 -c 指定的字符串

          如果你只需要快速地檢查某些內(nèi)容,則可以在命令行中將代碼作為字符串傳遞。

          # 使用 python 的 -c 參數(shù)
          python -c "print('hi')"

          當(dāng)需要檢查僅一行或兩行代碼時(shí),我個(gè)人會(huì)使用它,而不是啟動(dòng) REPL(譯注:Read Eval Print Loop,即交互式解釋器,例如在 windows 控制臺(tái)中輸入python, 就會(huì)進(jìn)入交互式解釋器。-c 參數(shù)用法可以省去進(jìn)入解釋器界面的過程)

          3、文件的路徑

          最眾所周知的傳代碼給 python 的方法很可能是通過文件路徑。

          # 指定 python 的文件路徑
          python spam.py

          要實(shí)現(xiàn)這一點(diǎn)的關(guān)鍵是將包含該文件的目錄放到sys.path里。這樣你的所有導(dǎo)入都可以繼續(xù)使用。但這也是為什么你不能/不應(yīng)該傳入包含在一個(gè)包里的模塊路徑。因?yàn)?code style="font-size: inherit;line-height: inherit;padding: 1px 2px;border-radius: 2px;color: rgb(248, 35, 117);background: rgb(248, 248, 248);">sys.path可能不包含該包的目錄,因此所有的導(dǎo)入將相對(duì)于與你預(yù)期的包不同的目錄。(如果你是在代碼所在文件目錄下,可以直接使用此命令,也就是我們通常在命令行下執(zhí)行文件的情況

          4、對(duì)包使用 -m

          執(zhí)行 Python 包的正確方法是使用 -m 并指定要運(yùn)行的包名。

          python -m spam

          它在底層使用了runpy[5]。要在你的項(xiàng)目中做到這點(diǎn),只需要在包里指定一個(gè)__main__.py文件,它將被當(dāng)成__main__執(zhí)行。而且子模塊可以像任何其它模塊一樣導(dǎo)入,因此你可以對(duì)其進(jìn)行各種測(cè)試。

          我知道有些人喜歡在一個(gè)包里寫一個(gè)main子模塊,然后將其__main__.py寫成:

          from . import main

          if __name__ == "__main__":
              main.main()

          就我個(gè)人而言,我不感冒于單獨(dú)的main模塊,而是直接將所有相關(guān)的代碼放入__main__.py,因?yàn)槲腋杏X這些模塊名是多余的。

          (譯注:即作者不關(guān)心作為入口文件的"main"或者“__main__”模塊,因?yàn)閳?zhí)行時(shí)只需用它們的包名即可。我認(rèn)為這也暗示了入口模塊不該再被其它模塊 import

          5、目錄

          定義__main__.py也可以擴(kuò)展到目錄。如果你看一下促成此博客文章的示例,python news可執(zhí)行,就是因?yàn)?news 目錄有一個(gè) __main__.py 文件。該目錄就像一個(gè)文件路徑被 Python 執(zhí)行了。

          現(xiàn)在你可能會(huì)問:“為什么不直接指定文件路徑呢?”好吧,坦白說,關(guān)于文件路徑,有件事得說清楚。??在發(fā)布過程中,我可以簡(jiǎn)單地寫上說明,讓運(yùn)行python news/announce.py,但是并沒有確切的理由說明這種機(jī)制何時(shí)存在。

          再加上我以后可以更改文件名,而且沒人會(huì)注意到。再加上我知道代碼會(huì)帶有輔助文件,因此將其放在目錄中而不是單獨(dú)作為單個(gè)文件是有意義的。

          當(dāng)然,我也可以將它變?yōu)橐粋€(gè)使用 -m 的包,但是沒必要,因?yàn)?announce 腳本很簡(jiǎn)單,我知道它要保持成為一個(gè)單獨(dú)的自足的文件(少于 200 行,并且測(cè)試模塊也大約是相同的長(zhǎng)度)

          況且,__main__.py文件非常簡(jiǎn)單。

          import runpy
          # Change 'announce' to whatever module you want to run.
          runpy.run_module('announce', run_name='__main__', alter_sys=True)

          現(xiàn)在顯然必須要處理依賴關(guān)系,但是如果你的腳本僅使用標(biāo)準(zhǔn)庫(kù)或?qū)⒁蕾嚹K放在__main__.py旁邊(譯注:即同級(jí)目錄),那么就足夠了!

          (譯注:我覺得作者在此有點(diǎn)“炫技”了,因?yàn)檫@種寫法的前提是得知道 runpy 的用法,但是就像前一條所寫的用 -m 參數(shù)運(yùn)行一個(gè)包,在底層也是用了 runpy。不過炫技的好處也非常明顯,即__main__.py 里不用導(dǎo)入 announce 模塊,還是以它為主模塊執(zhí)行,也就不會(huì)破壞原來的依賴導(dǎo)入關(guān)系)

          6、執(zhí)行一個(gè)壓縮文件

          如果你確實(shí)有多個(gè)文件和/或依賴模塊,并且希望將所有代碼作為一個(gè)單元發(fā)布,你可以用一個(gè)__main__.py,放置在一個(gè)壓縮文件中,并把壓縮文件所在目錄放在 sys.path 里,Python 會(huì)替你運(yùn)行__main__.py文件。

          # 將一個(gè)壓縮包傳給 Python
          python app.pyz

          人們現(xiàn)在習(xí)慣上用 .pyz 文件擴(kuò)展名來命名此類壓縮文件,但這純粹是傳統(tǒng),不會(huì)影響任何東西;你當(dāng)然也可以用 .zip 文件擴(kuò)展名。

          為了簡(jiǎn)化創(chuàng)建此類可執(zhí)行的壓縮文件,標(biāo)準(zhǔn)庫(kù)提供了zipapp[7]模塊。它會(huì)為你生成__main__.py并添加一條組織行(shebang line),因此你甚至不需要指定 python,如果你不想在 UNIX 上指定它的話。如果你想移動(dòng)一堆純 Python 代碼,這是一種不錯(cuò)的方法。

          不幸的是,僅當(dāng)壓縮文件包含的所有代碼都是純 Python 時(shí),才能這樣運(yùn)行壓縮文件。執(zhí)行壓縮文件對(duì)擴(kuò)展模塊無效(這就是為什么 setuptools 有一個(gè) zip_safe[8]標(biāo)志的原因)。(譯注:擴(kuò)展模塊 extension module,即 C/C++ 之類的非 Python 文件)

          要加載擴(kuò)展模塊,Python 必須調(diào)用 dlopen()[9]函數(shù),它要傳入一個(gè)文件路徑,但當(dāng)該文件路徑就包含在壓縮文件內(nèi)時(shí),這顯然不起作用。

          我知道至少有一個(gè)人與 glibc 團(tuán)隊(duì)交談過,關(guān)于支持將內(nèi)存緩沖區(qū)傳入壓縮文件,以便 Python 可以將擴(kuò)展模塊讀入內(nèi)存,并將其傳給壓縮文件,但是如果內(nèi)存為此服務(wù),glibc 團(tuán)隊(duì)并不同意。

          但是,并非所有希望都喪失了!你可以使用諸如shiv[10]之類的項(xiàng)目,它會(huì)捆綁(bundle)你的代碼,然后提供一個(gè)__main__.py來處理壓縮文件的提取、緩存,然后為你執(zhí)行代碼。盡管不如純 Python 解決方案理想,但它確實(shí)可行,并且在這種情況下算得上是優(yōu)雅的。

          (譯注:翻譯水平有限,難免偏差。我加注了部分內(nèi)容,希望有助于閱讀。如果文章對(duì)你有幫助,歡迎轉(zhuǎn)發(fā)/點(diǎn)贊/收藏~)

          參考鏈接

          [0] https://snarky.ca/the-many-ways-to-pass-code-to-python-from-the-terminal/

          [1] https://marketplace.visualstudio.com/items?itemName=ms-python.python

          [2] https://github.com/microsoft/vscode-python/tree/master/news

          [3] https://pypi.org/project/towncrier

          [4] https://snarky.ca/why-you-should-use-python-m-pip

          [5] https://docs.python.org/3/library/runpy.html#module-runpy

          [6] https://mp.weixin.qq.com/s/1ehySR5NH2v1U8WIlXflEQ

          [7] https://docs.python.org/3/library/zipapp.html#module-zipapp

          [8] https://setuptools.readthedocs.io/en/latest/setuptools.html#setting-the-zip-safe-flag

          [9] https://linux.die.net/man/3/dlopen

          [10] https://pypi.org/project/shiv


          _往期文章推薦_

          命令行常用命令




          如需了解付費(fèi)精品課程教學(xué)答疑服務(wù)
          請(qǐng)?jiān)?strong style="max-width: 100%;overflow-wrap: break-word !important;box-sizing: border-box !important;">Crossin的編程教室內(nèi)回復(fù): 666

          瀏覽 26
          點(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>
                  操逼的三级片的视频 | 中文字幕超碰在线播放 | 69久蜜桃人妻无码精品一区 | 亚洲日本高清 | 国产一级电影在线播放 |