Python項目中如何優雅的import

Python項目中如何優雅的import

前言

  • 以前有一篇關於Python編碼規範的隨筆, 可是寫的比較雜亂, 由於提到了import語句, 在篇文章中, 我專門來說Python項目中如何更好的import

標準庫與第三方庫的導入

  • 導入一個模塊, 若是模塊名太長, 則使用import as; 若是是導入子模塊, 則使用from import as
  • 若是須要導入類的, 則使用from import導入類, 若是要導入某一個模塊的多各種的話, 則類名使用逗號分隔
  • 示例
    1. 導入sklearn中的svm中的SVC類
    import sklearn.svm
    from sklearn.svm import SVC
    1. 導入numpy中的random模塊
    import numpy.random as nprand
  • 總結: 若是導入類的話, 必定是import somemod 和 from somemod import class兩個語句組成的; 若是導入一個不一樣的模塊的則, 則通常就是import somemod

項目模塊導入

  • 項目目錄
wxoa ›› tree -Cl
.
├── main.py
├── test
└── wxoa
    ├── __init__.py
    ├── __pycache__
    │   └── __init__.cpython-35.pyc
    ├── entity
    │   ├── __init__.py
    │   ├── __pycache__
    │   │   ├── __init__.cpython-35.pyc
    │   │   └── user.cpython-35.pyc
    │   └── user.py
    └── util
        ├── __init__.py
        ├── __pycache__
        │   ├── __init__.cpython-35.pyc
        │   └── ioutil.cpython-35.pyc
        └── ioutil.py

7 directories, 12 files
  • 主程序爲main.py, 項目名爲wxoa, 存放源代碼的目錄也叫wxoa, 也是一個python package
  • 導入規則(在第一次寫這篇文章的時候我喜歡相對導入(覺得google的sklearn是採用這種方式的, 可是在test中使用的是絕對導入(sklearn在test.py函數中直接使用絕對路徑, 由於已經寫好的sklearn已經安裝到了python路徑中了(sklearn的test是在這種狀況下進行測試的), 而通常咱們的項目是沒有安裝到python路徑中)), 可是官方建議絕對導入, 若是要使用絕對導入有不報錯的話, 個人方法是這隻軟連接)
    • 存在python package(因此這裏不包含main.py)中的python文件包導入的規則
      • 使用from . import somemod導入當前目錄下的模塊
      • 使用from ..somemod import submod導入上一級目錄的somemod目錄下的submod模塊
      • 若是名稱太長則使用as縮減
    • 不在python package(就是這裏的main.py和test目錄下的文件)中的python文件的導入規則
      • 使用from somemod.submod.subsubmod import some導入, 注意這裏不使用.號起頭, 關於使用., ..的做用在下面會說明, 若是使用了.起頭則會報錯, 提示父模塊沒有加載
      • 其中somemod就是咱們的源碼的python package包名, 在這裏就是wxoa
      • 若是名稱太長則使用as縮減

關於.和..

  • 在包導入中, 若是出現了.和..起頭, 則會涉及到package(不是module)的關係, ..表示上一級package, 這個上一級package須要有一個__init__.py纔是合法的, .表示當前package, 當前package須要有一個__init__.py纔是合法的java

  • .和..涉及到的python程序的啓動項, 這裏會比較複雜, 簡而言之, 在涉及到..表示的上級package的時候, 若是python程序的啓動文件就是在這裏則Python解釋器不會認爲..表示的上級目錄的package是一個合法的目錄, 儘管有__init__.py文件, 所以會報錯; 這樣就給代碼測試帶來的麻煩, 不能直接在使用..和.中直接測試代碼, 也就是
    if __name__ == '__main__': pass
    由於這樣已啓動程序就會報錯, 因此報錯, 在下面提出解決方案python

關於.和..帶來的麻煩的解決方案

  • 和上面展現的項目目錄同樣, 主啓動程序, 項目源代碼(主要是模塊), 測試代碼分離, main.py在項目目錄下, test(普通的文件夾, 存放python測試文件, 運行的時候cd ..目錄, 也就是在醒目目錄下, 使用python -m test.test1 執行程序)也在項目目錄下, 項目源代碼就是wxoa
  • 在main.py和test目錄下的python文件中導入本身項目中的模塊, 就不要使用.和..起頭了, 不然會報錯, 而是使用絕對路徑, 如這裏的, from wxoa.service import user

關於import

  • import在默認的狀況下是查看__name__屬性判斷是否加載的, 若是這個模塊是__main__則它就是top level(頂級)的, 沒有上一級目錄, 因此from .. import ....是會把報錯的, 在python3中的添加了__package__來解決這個問題, 在執行有from ..import ...的文件的時候, 使用python -m pkg.modname 執行modname.py文件, 將__package__從None改成pkg.modname才能正確的運行程序, 當__package__生效的時候, __name__在導入模塊的時候會被忽略

不建議使用全路徑導入, 這樣狀況必須安裝第三方庫才能使用, 不然必定會出現import錯誤, 提示路徑找不到

關於Python編程

  • 雖然Python是面向對象編程, 可是經過開源項目you-get發現, 能夠將Python理解爲面向模塊開發, 模塊在Python也是對象, 面向模塊開發會讓一切都輕鬆起來, 模塊中定義的全局變量爲其屬性, 模塊中的函數爲其方法, 若是多個函數有聯繫, 再考慮將其封裝到一個類中, 在調用該模塊的時候, 通常經過一個模塊函數返回對象, 不用讓用戶過多的考慮__init__()方法的參數, 直接在模塊函數中配置好信息返回便可
  • 加入咱們開發一個util工具箱, 則創建一個util包(和Java的包同樣), 在裏面建立strings.py, log.py等模塊(相似於Java中的一些.java文件), 在log.py模塊文件中定義一些須要的函數, 函數之間有某種聯繫或者爲了方便起見能夠定義類封裝

關於模塊設計

  • 示例:
    • 建立一個工具包, 該包中有關於字符串和IO操做的內容
    1. 首先考慮都放在一個模塊文件中, 文件他們都是工具, 放在util.py中是能夠的
    2. 接着考慮到咱們不須要建立strings和io的類, 由於工具咱們只須要一個就能夠, 這與模塊是同樣的特性, 因此將全部的操做寫成函數, 若是這樣的話, 模塊中沒有類對函數進行分類, 函數都在util.py中會很混亂, 因此將util.py升級爲util包, 建立strings.py和io.py, 將對應的函數放入對應的模塊文件中
  • 示例1:
    • 坦克遊戲
    1. 考慮放到game.py模塊下
    2. tank, bullet, wall等都是遊戲中的對象, 而且他們與工具類不一樣, 他們不僅是一個對象, 而是能夠建立不少, 與模塊特性不一樣, 全部把他們都寫成類, 在game文件中經過類劃分是可行的方案
相關文章
相關標籤/搜索