漲見識了,在終端執行 Python 程式碼的 6 種方式!
阿新 • • 發佈:2020-06-06
原作:[BRETT CANNON](https://snarky.ca/author/brett/)
譯者:豌豆花下貓@Python貓
英文:[https://snarky.ca/the-many-ways-to-pass-code-to-python-from-the-terminal](https://snarky.ca/the-many-ways-to-pass-code-to-python-from-the-terminal)
為了我們推出的 [VS Code 的 Python 外掛](https://marketplace.visualstudio.com/items?itemName=ms-python.python) [1],我寫了一個[簡單的指令碼來生成變更日誌](https://github.com/microsoft/vscode-python/tree/master/news) [2](類似於[Towncrier](https://pypi.org/project/towncrier/) [3],但簡單些,支援 Markdown,符合我們的需求)。在釋出過程中,有一個步驟是執行`python news` ,它會將 Python 指向我們程式碼中的"news"目錄。
前幾天,一位合作者問這是如何工作的,似乎我們團隊中的每個人都知道如何使用`-m` ?(請參閱我的有關[帶 -m 使用 pip 的文章](https://snarky.ca/why-you-should-use-python-m-pip/) [4],瞭解原因)(譯註:關於此話題,我也寫過一篇[更為詳細的文章](https://mp.weixin.qq.com/s/co_OAaVQ49rPfgoAh6Pejw) )
這使我意識到其他人可能不知道有五花八門的方法可以將 Python 指向要執行的程式碼,因此有了這篇文章。
## 1、通過標準輸入和管道
因為如何用管道傳東西給一個程序是屬於 shell 的內容,我不打算深入解釋。毋庸置疑,你可以將程式碼傳遞到 Python 中。
```shell
# 管道傳內容給 python
echo "print('hi')" | python
```
如果將檔案重定向到 Python,這顯然也可以。
```shell
# 重定向一個檔案給 python
python < spam.py
```
歸功於 Python 的 UNIX 傳統,這些都不太令人感到意外。
## 2、通過`-c` 指定的字串
如果你只需要快速地檢查某些內容,則可以在命令列中將程式碼作為字串傳遞。
```python
# 使用 python 的 -c 引數
python -c "print('hi')"
```
當需要檢查僅一行或兩行程式碼時,我個人會使用它,而不是啟動 REPL(譯註:Read Eval Print Loop,即互動式直譯器,例如在 windows 控制檯中輸入`python`, 就會進入互動式直譯器。-c 引數用法可以省去進入直譯器介面的過程) 。
## 3、檔案的路徑
最眾所周知的傳程式碼給 python 的方法很可能是通過檔案路徑。
```python
# 指定 python 的檔案路徑
python spam.py
```
要實現這一點的關鍵是將包含該檔案的目錄放到`sys.path` 裡。這樣你的所有匯入都可以繼續使用。但這也是為什麼你不能/不應該傳入包含在一個包裡的模組路徑。因為`sys.path` 可能不包含該包的目錄,因此所有的匯入將相對於與你預期的包不同的目錄。
## 4、對包使用 -m
執行 Python 包的正確方法是使用 -m 並指定要執行的包名。
```
python -m spam
```
它在底層使用了[runpy](https://docs.python.org/3/library/runpy.html#module-runpy) [5]。要在你的專案中做到這點,只需要在包裡指定一個`__main__.py` 檔案,它將被當成`__main__` 執行。而且子模組可以像任何其它模組一樣匯入,因此你可以對其進行各種測試。
我知道有些人喜歡在一個包裡寫一個`main` 子模組,然後將其`__main__.py` 寫成:
```python
from . import main
if __name__ == "__main__":
main.main()
```
就我個人而言,我不感冒於單獨的`main` 模組,而是直接將所有相關的程式碼放入`__main__.py` ,因為我感覺這些模組名是多餘的。
(譯註:即作者不關心作為入口檔案的"main"或者“\_\_main_\_”模組,因為執行時只需用它們的包名即可。我認為這也暗示了入口模組不該再被其它模組 import。我[上篇文章](https://mp.weixin.qq.com/s/1ehySR5NH2v1U8WIlXflEQ) [6]比作者的觀點激進,認為連那句 if 語句都不該寫。)
## 5、目錄
定義`__main__.py`也可以擴充套件到目錄。如果你看一下促成此部落格文章的示例,`python news` 可執行,就是因為 news 目錄有一個 `__main__.py` 檔案。該目錄就像一個檔案路徑被 Python 執行了。
![](http://ww1.sinaimg.cn/large/68b02e3bgy1gfileouktjj20x80mfmzk.jpg)
現在你可能會問:“為什麼不直接指定檔案路徑呢?”好吧,坦白說,關於檔案路徑,有件事得說清楚。