Python3快速入門(四)——Python包管理

一、Python包簡介

1、包

Python中使用包管理模塊,包通常對應一個目錄,必須在目錄下創建一個 init .py模塊, init .py模塊的模塊名稱即為包名,Python才會將目錄解析為包。
init .py文件內可以定義初始化包的內容,導入包的內容,限制包內模塊的導出。
init .py文件可以為空,也可以是一個模塊,其模塊名稱為包名稱。
導入包或包的模塊、變量、函數時, init .py文件會被自動執行。

2、模塊

Python中一個.py文件就是一個模塊。
Python 中用?import?或者?from...import?來導入相應的模塊。
將整個模塊(somemodule)導入,格式為:?import somemodule
從某個模塊中導入某個函數或變量,格式為:?from somemodule import somefunction
從某個模塊中導入多個函數,格式為:?from somemodule import firstfunc, secondfunc, thirdfunc
將某個模塊中的全部函數或變量導入,格式為: ?from somemodule import *

            
              import sys
print('================Python import module==========================')
print('命令行參數為:')
for i in sys.argv:
    print(i)
print("python 路徑為", sys.path)

from sys import argv, path  # 導入特定的成員

print('================python from import===================================')
print(argv)
print(path)
            
          

對導入的模塊進行重命名
Import package.module as name
import導入包或模塊時,如果導入模塊較多需要換行,可以使用反斜杠,或是將使用小括號將包含所有的模塊。
包和模塊不會被重復導入。

3、模塊的內置變量

模塊內部預定義了內置變量:
name :當前模塊名稱
package :當前模塊所屬包的名稱
doc :當前模塊的注釋內容
file :當前文件

            
              # -*- coding:utf-8 -*-
print("name: " + __name__)
print("package: " + (__package__ or "當前模塊不屬于任何包"))
print("doc: " + (__doc__ or "當前模塊沒有任何注釋"))
print("file: " + __file__)
# name: __main__
# package: 當前模塊不屬于任何包
# doc: 當前模塊沒有任何注釋
# file: test.py
            
          

如果某個文件被當作入口文件,內置變量 package 沒有值, name 值為 main doc file 值為文件名稱(不含路徑)。
每個模塊都可以任意寫一些沒有縮進的代碼,并且在載入時自動執行,為了區分模塊是主執行文件還是被調用的模塊文件,Python引入了一個變量 name ,當文件是被調用時, name 的值為模塊名,當文件作為入口被執行時, name 為' main '。因此,可以在每個模塊中寫上測試代碼,測試代碼僅當模塊被Python直接執行時才會運行,代碼和測試結合在一起,完美實現對測試驅動開發(TDD)的支持。

            
              if __name__ == "__main__":
    function_name()
            
          

將一個模塊文件作為模塊執行而不是應用執行的命令如下:
python3 -m package.module

二、Python包管理

1、導入包和模塊

import只能導入包和模塊,不能直接導入變量或者函數。對于多層包嵌套后導致導入名稱過長,可以為其重命名。

            
              import package1.package2.module_name
import package1
import package1.module_name
import package1.package2.module_name as new_name
            
          

導入包和模塊時需要避免循環導入,兩個或者多個模塊文件互相導入會報錯。
Python在導入模塊時,會執行模塊里的所有內容,但多次導入只會執行一次。
Import導入包或模塊時,Python 解釋器尋找模塊的優先級如下:
A、當前目錄
B、環境變量PYTHONPATH
C、sys.path(list 類型)
模塊在被導入執行時,Python解釋器為加快程序的啟動速度,會在與模塊文件同一目錄下自動生成.pyc文件,.pyc是經過編譯后的字節碼。
Python使用縮進對齊組織代碼的執行,所有沒有縮進的代碼(非函數定義和類定義),都會在載入時自動執行。

2、導入變量和函數

導入某個模塊的變量,多個使用逗號分隔
from package1.package2.module_name import variable_name

導入某個模塊的函數,多個使用逗號分隔
from package1.package2.module_name import function_name
導入某個包的某個模塊,多個使用逗號分隔
from package1 import module_name
導入模塊的所有變量和函數
from package1.module_name import *
在模塊內使用內置 all 屬性指定本模塊可以導出的變量或函數,外部導入只能使用指定的變量或函數。
在模塊( *.py )中使用導出 all 列表里的類、函數、變量等成員,否則將導出所有不以下劃線開頭(私有)的成員,在模塊中使用 all 屬性可避免在相互引用時的命名沖突。

            
              #!/usr/bin/python3

__all__ = ["variable1", "variable2", "function_name1", "function_name2"]

variable1 = 0
variable2 = 0

def function_name1(args):
    pass

def function_name2(args):
    pass
            
          

在導入變量和函數時,如果變量和函數太多需要換行,則可以使用反斜杠換行或是使用小括號修飾多個變量或函數。

            
              from package1.module_name import variable1, variable2 \
    variable3, function_name1

from package1.module_name import (variable1, variable2, 
                                  function_name2, function_name2)
            
          

3、頂級包

頂級包與入口文件 main.py 的位置有關,與 main.py 同級的包是頂級包,因此main.py入口文件不屬于任何包。

4、相對導入

相對導入是導入模塊時指定被導入模塊名稱的相對路徑。
import 不支持相對導入,只能使用 from ... import ... 格式實現相對導入,
“ . ?.. ?... ” 來表示相對路徑,一個點表示當前包,兩個點表示上一級包,以此類推。
入口文件中沒有包的概念,因此不能使用相對導入。
使用相對導入不要超出頂級包,入口文件同級的包都不能使用相對導入。
在main.py如果作為模塊執行時,可以使用相對導入,此時使用如下命令執行:
python3 -m main.py

5、絕對導入

絕對導入是導入時必須指定從頂級包到被導入模塊名稱的完整路徑,可以使用import 和 from ... import ...進行導入。

6、 init .py模塊

init .py文件存在包的根目錄下,當包或者包中的任意模塊或模塊中變量、函數被導入時, init .py中內容會首先自動被執行。因此, init .py文件可以實現如下應用:
A、限制本包的模塊導入
init .py中寫入內置函數 all ,決定哪些模塊可以被外部導入。
__all__ = ["module_name1", "module_name2"]
B、批量導入
如果包內多個模塊文件都需要用到某些模塊文件時,可以在包的 init .py文件中導入需要的模塊文件,然后就可以在本包不同的模塊文件中直接使用導入的模塊 。

三、Python項目結構

1、Python文件結構

通常,Python文件結構如下:

            
              #!/usr/bin/python3

# 模塊文檔
"""
    This is an example.
"""

# 模塊導入
import sys
import os

# 定義全局變量
debug = True

# 定義類
class class_name:
    pass

# 定義函數
def function_name():
    pass

# 主程序
if __name__ == "__main__":
    function_name()
            
          

2、Python項目目錄結構

通常,Python項目的目錄結構如下:
README:項目說明文檔。
bin(scripts):存放項目的可執行腳本。
project_name:存放項目的所有源代碼,程序的入口文件最好命名為main.py。
docs: 存放項目文檔。
tests:測試代碼目錄。
extras:項目擴展部分,不屬于項目必需的部分,存放與項目相關的sample、poc,通常子目錄如下dev_example、production_example、test1_poc、test2_poc。
setup.py:項目安裝、部署、打包的腳本。
requirements.txt:存放軟件依賴的外部Python包列表。
README:項目說明文件。
LICENSE.txt:版權聲明
ChangeLog.txt:版本變更日志記錄
AUTHORS:作者清單
INSTALL:安裝說明
MANIFEST.in:裝箱清單文件
MAKEFILE:編譯腳本

四、pipenv包管理工具

1、pipenv簡介

Python項目開發中,在開發需求完成并測試好后,需要發布到正式服務器,此時會面臨環境依賴問題。Python項目可能會有多個第三方模塊包,并且可能會有版本約束問題,因此需要一個虛擬環境,在虛擬環境里面模擬出跟服務器相同的環境。
pipenv ,全稱為Python Development Workflow for Humans,旨在為開發項目自動創建和管理虛擬環境并管理 Python 包,是virtualenv 和pip的合集,通過創建指定python版本的虛擬環境和安裝依賴包,提供各個項目隔離的開發環境。

2、pipenv安裝

對于Python3,安裝命令如下:
pip3?install?pipenv
安裝結果查看:
pipenv?–version

3、pipenv常用命令

pipenv?--three
pipenv?--?two
pipenv --python 3.x.x
pipenv --python 2.x.x
創建虛擬環境,并指定Python版本
pipenv shell從系統環境切換到虛擬環境
pipenv install xxxx在虛擬環境安裝軟件包
exit退出虛擬環境
pipenv uninstall [module_name] 刪除Python包
pipenv --rm刪除虛擬環境
pipenv --where 列出本地工程路徑
pipenv --venv 列出虛擬環境路徑
pipenv --py 列出虛擬環境的Python可執行文件
pipenv install 創建虛擬環境
pipenv install [moduel] 安裝包
pipenv install [moduel] --dev 安裝包到開發環境
pipenv uninstall [module] 卸載包
pipenv graph 查看包依賴
pipenv lock 生成lockfile
pipenv run python [pyfile] 運行py文件
pipenv uninstall --all?卸載全部包并從Pipfile中移除

4、更換源

pipenv默認的Pipfile?文件中指定使用官方源鎖定依賴,會導致速度過慢,解決方案自然是更換國內源,常用國內源如下:
阿里云:http://mirrors.aliyun.com/pypi/simple/
清華大學:https://pypi.tuna.tsinghua.edu.cn/simple/
中國科學技術大學:https://pypi.mirrors.ustc.edu.cn/simple/
源更換需要將Pipfile?文件中url的值替換為國內源。

            
              [[source]]
name = "pypi"
url = "http://mirrors.aliyun.com/pypi/simple/ "
verify_ssl = true

[dev-packages]

[packages]
pymysql = "*"
pymango = "*"
mysql-connector = "*"
mysqldb = "*"
mysql-python = "*"

[requires]
python_version = "3.7"