A. Python項目生成requirements的三種方式
第一種方式適用於通過conda來管理/安裝項目依賴包,生成的文件內容如下:
第二種方式適用於通過pip來管理/安裝項目依賴包,生成的文件內容如下:
所以看到通過這種方式生成的requirements文件中,通過conda安裝的包並不能給出包版本,而是 @ file:////... 這種形式。
如果沒有使用虛擬環境,或虛擬環境中有很多項目沒有使用的包,則上面兩種方式都將環境中的所有包版本記錄在requirements文件中,不便於項目移植,這時候需要第三種方式:
上面第一條命令默認安裝到全局的環境中
如果上面的命令不能安裝到指定Python版本的虛擬環境中,則
可用pycharm,進入命令行,運行:
參考:
python生成requirements.txt的兩種方法 python 腳本之家 (jb51.net)
我的項目在conda環境中使用的軟體包-python黑洞網 (pythonheidong.com)
pipreqs · PyPI
User Guide - pip documentation v22.1.2 (pypa.io)
B. python和anaconda有哪些區別
1、安裝包大小不同
python自身缺少numpy、matplotlib、scipy、scikit-learn等一系列包,需要安裝pip來導入這些包才能進行相應運算。
Anaconda(開源的Python包管理器)是一個python發行版,包含了conda、Python等180多個科學包及其依賴項。包含了大量的包,使用anaconda無需再去額外安裝所需包。
2、作用不同
Python語法和動態類型,以及解釋型語言的本質,使它成為多數平台上寫腳本和快速開發應用的編程語言。anaconda可以用於在同一個機器上安裝不同版本的軟體包及其依賴,並能夠在不同的環境之間切換。
3、性質不同
Anaconda是一個打包的集合,裡面預裝好了conda、某個版本的python、眾多packages、科學計算工具等等,所以也稱為Python的一種發行版。
Python 是一個高層次的結合了解釋性、編譯性、互動性和面向對象的腳本語言。
C. 怎樣將python程序及其依賴打包成rpm包部署
可以的,雖然說pip比較流行,但rpm從原理上完全可以覆蓋這些部署過程,只有一些小的要求:
所有環境的Python安裝方式必須一致,不能存在某些Python是2.6,某些是2.7,某些裝在/usr/local下面,某些在/usr/lib下面之類的情況
如果帶有C擴展的話,鏈接到的庫應當是來自某個rpm包的。如果沒有的話就簡單多了。
如果有依賴的其他Python包的話,需要把依賴的包也做成rpm;實在偷懶也可以打進同一個rpm中。
實際上發行版中有許多Python庫都以rpm的形式提供,不過一般我們嫌它版本舊,更傾向於用pip管理一組新的。
要寫一個rpm spec,可以從頭自己寫,也可以參考一些其他軟體的spec,我建議你採用後者,既然你們公司已經廣泛使用rpm了,那肯定有很多本公司的spec可以參考,也有人可以問。
回到話題,寫rpm spec,或者說rpmbuild的過程,分成以下步驟:
部署源代碼,一般來說將一個.tar.gz復制到SRC目錄中,然後用%setup宏就可以了,這個宏也基本上沒干什麼特別的事,就是把.tar.gz解壓縮了一下,然後進入相應目錄。.tar.gz只要從git中取出干凈的源代碼,整個目錄打成tar包就可以了。好像還有專門的git-archive命令。
build過程,對應C/C++項目中的./configure, make。對Python項目來說一般可以跳過,因為setup.py都會搞定。也可以選擇在這個階段使用setup.py進行build,build出一個wheel包來,這是我推薦的方法,因為wheel包和直接setup.py install的目錄結構有一些差異,而pip安裝默認是按照wheel的方式。也就是說在這一步調用:setup.py bdist_wheel。再精細一點可以指定build的目標為build目錄,這樣需要cleanup的時候容易一些。
install過程,對應C/C++項目中的make install。一般來說我們平時怎麼裝這個軟體,這一步就怎麼裝,所以我們也是使用setup.py。唯一的技巧在於,我們需要指定安裝的目標到rpmbuild根的某個目錄下面,而不是系統的目錄。這個目錄在install開始之前應當被清空。可以參考其他spec。對於我們來說,就是將Python的庫安裝到指定的目錄,而不是系統的site-packges當中。如果你在build這一步已經打包了wheel,那麼使用wheel install命令、指定目標文件夾就可以了。
打包過程,rpm的打包原理非常簡單,最開始install的目錄是空的,install完成後裡面有了一堆文件,那麼就按照文件列表將這一堆文件打包、然後指定每個文件將來應當安裝到什麼位置。對於Python項目來說,一般會安裝package名的目錄和EGGINFO兩個目錄,將這兩個目錄連同裡面所有的內容一起加入%files段就可以了。如果你要部署的是某個應用,一般你還會希望將init.d中的啟動腳本、或者 systemd的配置文件以及其他應用的配置文件一起部署了,可以在install的過程中將這些文件從源文件目錄中復制到目標文件夾里,然後加到files段裡面。
安裝、卸載腳本。表現為%pre, %post之類的段一般來說如果你有服務要安裝的話,需要在這里使用chkconfig, chkconfig on,或者systemd的話就是systemctl enable。如果你希望安裝完有個機會修改配置文件,可以選擇在首次安裝的時候不要啟動服務,而在update的時候啟動服務,這可以通過腳本傳進的第一個命令行參數$1進行判斷,0、1、2表示不同的情況(分別是卸載、安裝、更新,具體的記不清了),可以參考其他人寫的spec;也可以選擇安裝完永遠直接啟動,在post中使用service xxx start, 在preuninstall的時候使用service xxx stop。
rpm的功能還是很強大的,除了跟pip共通的功能以外,它有一個顯著的好處就是可以幫助你同時管理服務的配置、啟動和停止,從而簡化部署過程。不過要注意如果使用rpm的話就不要同時使用pip,否則pip更新過的庫,rpm卸載或更新時會沖突。
有第三方依賴的時候,一種方法是為每個依賴項寫一個獨立的spec,裡面內容都是上面這樣的直接調用setup.py,或者更簡單一些,在install的時候直接調用pip就可以;然後在需要這些依賴項的rpm包的spec當中寫上Require信息,跟pip體系的requirements差不多。偷懶也可以在同一個rpm中打了一堆Python包進去,但是如果有多個獨立安裝的rpm都打了同一個Python包,就會沖突,要注意。
其實用習慣了會覺得也不比pip差,需要跟非Python組件混合部署的時候反而會覺得簡單了很多。
D. pyenv下python依賴的路徑和打包項目
一個很好用的打包工具:pyinstaller
很簡單,cd到目標項目的.py目錄下,運行 pyinstaller -F file.py -F:表示只生成一個可執行文件,如果不加則會在dist文件夾下生成很多文件和一個可執行文件。
successfully之後,當前目錄下會生成兩個文件夾,一個dist,一個build,我們所需要的文件在dist裡面。
直接運行就可以了
為啥不用這個方法呢,因為在python的包中,有的完全是python的, 而有的並不是純python的 ,那麼接下來介紹方法二,如何安全的提取打包。
我是從pycharm中找到了蛛絲馬跡
現在全都找到了,如果你可以打開.py文件,那麼路徑更好找,直接cd過去就ok了:
回到之前我們的疑問: 怎麼判斷安裝包是不是純python的呢?
這裡面的.so文件就不是python的文件,.py/.pyc是。所以這種包無法打包,只能到目標環境下手動安裝。
找到我們需要的包,cp出去放到 sys.path 可以找到的路徑下就可以了(放到你要run的那個文件夾里),結果如下:
重新創建一個虛擬環境,運行下export.py查看能否正常運行就ok了。
E. python多介面有依賴如何調用
方法如下:
1. 對於單介面測試如果依賴介面只需要在測試開始執行一次,那麼可以將依賴介面的請求放在類級前置方法中,然後通過全局變數或者當前用例類屬性來傳遞依賴數據。
2. 對於單介面測試如果依賴介面需要在每個用例前執行,那麼可以將依賴介面的請求放在方法級前置方法中,然後通過用例對象屬性來傳遞依賴數據
3. 對於多介面的業務流測試,可以將下一個介面需要依賴的數據通過當前用例類屬性來傳遞依賴數據。
Python由荷蘭數學和計算機科學研究學會的Guido van Rossum 於1990 年代初設計,作為一門叫做ABC語言的替代品。 Python提供了高效的高級數據結構,還能簡單有效地面向對象編程。Python語法和動態類型,以及解釋型語言的本質,使它成為多數平台上寫腳本和快速開發應用的編程語言,隨著版本的不斷更新和語言新功能的添加,逐漸被用於獨立的、大型項目的開發。
F. Linux 下Python 腳本編寫的"奇技淫巧"
「 生命完美的答案,無非走過沒有遺憾 ---《天藍》」
「如何能夠解析腳本運行命令行選項(位於 sys.argv 中)」
argparse 模塊可被用來解析命令行選項
常用來定義一個腳本的說明文檔,一般我們寫python腳本會通過 if..else 的方式來提供一個腳本說明文檔,python不支持switch。所以很麻煩,其實,我們可以通過 argparse 來編寫說明文檔。
我們來看看怎麼執行一個python腳本
對於熟悉Linux的小夥伴下面的文檔在熟悉不過了,這個一個標准Linxu軟體包的說明文檔,文檔中定義是軟體包的說明
來看看這個腳本是如何編寫的
為了解析命令行選項, 首先要創建一個 ArgumentParser 實例, 使用 add_argument() 方法聲明你想要支持的選項。在每個 add-argument() 調用中:
dest 參數指定解析結果被指派給屬性的名字。 metavar 參數被用來生成幫助信息。
action 參數 指定跟屬性對應的處理邏輯,通常的 值為 store , 被用來存儲 某個值 或將 多個參數值收集到一個列表中 。
nargs 參數收集 所有剩餘的命令行參數到一個列表中。在本例中它被用來構造一個文件名列表
action='store_true' 根據參數是否存在來設置一個位置 Boolean 標志:
action='store' 參數接受一個單獨值並將其存儲為一個字元串
如果一個都沒有,會提示缺少參數 -p/--pat
choices={'slow', 'fast'}, 參數說明接受一個值,但是會將其和可能的選擇值做比較,以檢測其合法性:
一旦參數選項被指定,你就可以執行 parser.parse() 方法了。它會處理 sys.argv 的值並返回一個結果實例。每個參數值會被設置成該實例中 add_argument() 方法的 dest 參數指定的屬性值。
還很多種其他方法解析命令行選項。可以會手動地處理 sys.argv 或者使用 getopt 模塊 。但是,如果你採用本節的方式,將會減少很多冗餘代碼,底層細節 argparse 模塊 已經幫你處理好了。你可能還會碰到使用 optparse 庫解析選項的代碼。盡管 optparse 和 argparse 很像 ,但是後者更先進,因此在新的程序中你應該使用它。
「你寫了個腳本,運行時需要一個密碼。此腳本是互動式的,因此不能將密碼在腳本中硬編碼,而是需要彈出一個密碼輸入提示,讓用戶自己輸入。」
Python 的 getpass 模塊 正是你所需要的。你可以讓你很輕松地彈出密碼輸入提示,並且不會在用戶終端顯示密碼。
代碼中 getpass.getuser() 不會彈出用戶名的輸入提示。它會根據該 用戶的 shell 環境 或者會依據 本地系統的密碼庫 (支持 pwd 模塊的平台)來使用 當前用戶的登錄名
在bash中編寫pytohn腳本接收外部數據的方式,一般情況下,對於一般變數,我們用命令行變數的方式比較多(手動的處理 sys.argv ),對於 文件內容或者bash命令輸出 直接通過腳本內部獲取需要的數據。
其實python 腳本也可以用其他方式來接收 傳遞給他的 文件數據或者bash命令輸出 ,包括將 命令行的輸出 通過 管道傳遞 給該腳本、 重定向文件到該腳本 ,或在 命令行中傳遞一個文件名 或 文件名列表 給該腳本。
這里通過 Python 內置的 fileinput 模塊 ,可以實現重 定向,管道,以文佳輸出 的方式傳遞數據到腳本內部
使用 fileinput.input() 方法可以獲取當前輸入腳本的數據,腳本裡面用一個 FileInput 迭代器接收
文件直接接收
重定向接收
管道方式接收
fileinput.input() 創建並返回一個 FileInput 類的實例,該實例可以被當做一個 上下文管理器 使用。因此,整合起來,如果我們要寫一個列印多個文件輸出的腳本,那麼我們需要在輸出中包含文件名和行號
「你想執行一個外部命令並以 Python 字元串的形式獲取執行結果。」
使用 subprocess.check_output() 函數。
執行下試試
如果被執行的命令以非零碼返回,就會拋出異常。下面的例子捕獲到錯誤並獲取返回碼:
默認情況下, check_output() 僅僅返回輸入到標准輸出的值。如果你需要 同時收集標准輸出和錯誤輸出 ,使用 stderr 參數:
如果你需要用一個超時機制來執行命令,使用 timeout 參數:
通常來講,命令的執行 不需要 使用到 底層 shell 環境(比如 sh、bash) 。一個字元串列表會被傳遞給一個 低級系統命令 ,比如 os.execve() 。
如果你想讓 命令被一個shell 執行 ,傳遞一個字元串參數,並設置參數 shell=True . 有時候你想要 Python 去執行一個復雜的 shell 命令 的時候這個就很有用了,比如管道流、I/O 重定向和其他特性。例如:
是在 shell 中執行命令會存在一定的安全風險,特別是當參數來自於用戶輸入時。這時候可以使用 shlex.quote() 函數 來將參數正確的用雙引用引起來。
使用 check_output() 函數 是執行 外部命令 並獲取其 返回值 的最簡單方式。但是,如果你需要對 子進程做更復雜的交互 ,比如給它發送輸入,你得採用另外一種方法。這時候可直接使用 subprocess.Popen 類。
關於子進程,簡單來看下
也可以進程列表同協程結合的方式。你既可以在子shell中 進行繁重的處理工作,同時也不會讓子shell的I/O受制於終端。
如果直接丟到後台會自動在終端輸出IO
subprocess 模塊對於依賴 TTY 的外部命令不合適用 。例如,你不能使用它來自動化一個用戶輸入密碼的任務(比如一個 ssh 會話)。這時候,你需要使用到第三方模塊了,比如基於著名的 expect 家族的工具(pexpect 或類似的)(pexpect可以理解為Linux下的expect的Python封裝、通過pexpect可以實現對ssh、ftp、passwd、telnet等命令行進行自動交互,而無需人工干涉來達到自動化的目的。比如我們可以模擬一個FTP登錄時所有交互,包括輸入主機地址、用戶名、密碼、上傳文件等,待出現異常還可以進行嘗試自動處理。)
「你想向標准錯誤列印一條消息並返回某個非零狀態碼來終止程序運行」
通過 python 的 raise SystemExit(3) 命令可以主動拋出一個錯誤,通過 sys.stderr.write 將命令寫到標準的輸出端
直接將消息作為參數傳給 SystemExit() ,那麼你可以省略其他步驟
拋出一個 SystemExit 異常,使用錯誤消息作為參數,它會將消息在 sys.stderr 中列印,然後程序以狀態碼 1 退出
「你需要知道當前終端的大小以便正確的格式化輸出。」
使用 os.get terminal size() 函數 來做到這一點。
「復制或移動文件和目錄,但是又不想調用 shell 命令。」
shutil 模塊 有很多便捷的函數可以復制文件和目錄。使用起來非常簡單
這里不多講,熟悉Linux的小夥伴應該不陌生。
默認情況下,對於 符號鏈接 這些命令處理的是它指向的東西文件。例如,如果 源文件 是一個 符號鏈接 ,那麼目標文件將會是 符號鏈接 指向的文件。如果你只想 復制符號鏈接本身 ,那麼需要指定 關鍵字 參數 follow_symlinks
tree() 可以讓你在復制過程中選擇性的忽略某些文件或目錄。你可以提供一個忽略函數,接受一個目錄名和文件名列表作為輸入,返回一個忽略的名稱列表。例如:
對於文件元數據信息, 2() 這樣的函數只能盡自己最大能力來保留它。 訪問時間、創建時間和許可權 這些基本信息會被保留,但是 對於所有者、ACLs、資源 fork 和其他更深層次的文件元信息就說不準了
通常不會去使用 shutil.tree() 函數 來執行 系統備份 。當處理文件名的時候,最好使用 os.path 中的函數來確保最大的可移植性
使用 tree() 復制文件夾的一個棘手的問題是對於錯誤的處理,可以使用異常塊處理,或者通過 參數 ignore dangling symlinks=True 忽略掉無效符號鏈接。
「創建或解壓常見格式的歸檔文件(比如.tar, .tgz 或.zip)」
shutil 模塊擁有兩個函數—— make archive() 和 unpack archive() 可派上用場,
make archive() 的第二個參數是期望的輸出格式。可以使用 get archive formats() 獲取所有支持的歸檔格式列表。
「你需要寫一個涉及到文件查找操作的腳本,比如對日誌歸檔文件的重命名工具,你不想在 Python 腳本中調用 shell,或者你要實現一些 shell 不能做的功能。」
查找文件,可使用 os.walk() 函數 ,傳一個頂級目錄名給它
os.walk() 方法 為我們 遍歷目錄樹 ,每次進入一個目錄,它會返回一個 三元組 ,包含 相對於查找目錄的相對路徑,一個該目錄下的目錄名列表,以及那個目錄下面的文件名列表。
對於每個元組,只需檢測一下目標文件名是否在文件列表中。如果是就使用 os.path.join() 合並路徑。為了避免奇怪的路徑名比如 ././foo//bar ,使用了另外兩個函數來修正結果
os.walk(start) 還有跨平台的優勢。並且,還能很輕松的加入其他的功能。我們再演示一個例子,下面的函數列印所有最近被修改過的文件:
列印10分鍾之前被修改的數據
「怎樣讀取普通.ini 格式的配置文件?」
configparser 模塊 能被用來讀取配置文件
編寫配置文件
如果有需要,你還能修改配置並使用 cfg.write() 方法將其寫回到文件中
「你希望在腳本和程序中將診斷信息寫入日誌文件。」
python 腳本列印日誌最簡單方式是使用 logging 模塊
五個日誌調用( critical(), error(), warning(), info(), debug() )以降序方式表示不同的嚴重級別。 basicConfig() 的 level 參數是一個 過濾器 。所有級別低於此級別的日誌消息都會被忽略掉。每個 logging 操作的參數是一個消息字元串,後面再跟一個或多個參數。構造最終的日誌消息的時候我們使用了 % 操作符來格式化消息字元串。
如果你想使用配置文件,可以像下面這樣修改 basicConfig() 調用:
logconfig.ini
在調用日誌操作前先執行下 basicConfig() 函數方法 ,可以找標准輸出或者文件中輸出
basicConfig() 在程序中只能被執行一次。如果你稍後想改變日誌配置,就需要先獲取 root logger ,然後直接修改它。
更多見日誌模塊文檔https://docs.python.org/3/howto/logging-cookbook.html
「你想給某個函數庫增加日誌功能,但是又不能影響到那些不使用日誌功能的程序。」
對於想要執行日誌操作的函數庫,你應該創建一個專屬的 logger 對象,並且像下面這樣初始化配置:
使用這個配置,默認情況下不會列印日誌,只有配置過日誌系統,那麼日誌消息列印就開始生效
通常來講,不應該在函數庫代碼中 自己配置日誌系統 ,或者是已經有個已經存在的日誌配置了。調用 getLogger( name ) 創建一個和調用模塊同名的 logger 模塊 。由於 模塊 都是唯一的,因此創建的 logger 也將是唯一 的。所以當前進程中只有一個logging會生效。
log.addHandler(logging.NullHandler()) 操作將一個 空處理器 綁定到剛剛已經創建好的 logger 對象 上。一個空處理器默認會忽略調用所有的日誌消息。因此,如果使用該函數庫的時候還沒有配置日誌,那麼將不會有消息或警告出現。
在這里,根日誌被配置成僅僅 輸出 ERROR 或更高級別的消息 。不過, somelib 的日誌級別被單獨配置成可以輸出 debug 級別的消息, 它的優先順序比全局配置高。像這樣更改單獨模塊的日誌配置對於調試來講是很方便的,因為你無需去更改任何的全局日誌配置——只需要修改你想要更多輸出的模塊的日誌等級。(這個還有待研究)
「你想記錄程序執行多個任務所花費的時間」
time 模塊 包含很多函數來執行跟時間有關的函數。盡管如此,通常我們會在此基礎之上構造一個更高級的介面來模擬一個計時器。
這個類定義了一個可以被用戶根據需要啟動、停止和重置的計時器。它會在elapsed 屬性中記錄整個消耗時間。下面是一個例子來演示怎樣使用它:
這里通過 __enter__,__exit__ ,使用 with 語句 以及上下文管理器協議可以省略計時器打開和關閉操作。(關於上下文管理協議,即with語句,為了讓一個對象兼容with語句,必須在這個對象的類中聲明 __enter__和__exit__方法, , __enter__ 在出現with語句被調用, __exit__ 在代碼執行完畢被調用,可以參考open()方法)
在計時中要考慮一個 底層的時間函數問題 。 一般來說, 使用 time.time() 或 time.clock() 計算的時間精度因操作系統的不同會有所不同。而使用 time.perf_counter() 函數可以確保使用系統上面 最精確的計時器 。
「你想對在 Unix 系統上面運行的程序設置內存或 CPU 的使用限制。」
resource 模塊 能同時執行這兩個任務。例如,要限制 CPU 時間,下面的代碼在windows平台執行不了,但是Linux是可以的。
程序運行時, SIGXCPU 信號 在時間過期時被生成,然後執行清理並退出。
這暫時沒有好的Demo...
程序運行到沒有多餘內存時會拋出 MemoryError 異常。
setrlimit() 函數 被用來設置特定資源上面的 軟限制和硬限制 。
setrlimit() 函數 還能被用來設置 子進程數量、打開文件數以及類似系統資源的限制(cgroup) 。
「通過腳本啟動瀏覽器並打開指定的 URL 網頁」
webbrowser 模塊 能被用來啟動一個瀏覽器,並且與平台無關
新窗口打卡網站
當前窗口打開一個tab頁
指定瀏覽器類型,可以使用 webbrowser.get() 函數
G. python和anaconda區別是什麼
python和anaconda的區別其實anaconda是包含python的,所以安裝了anaconda就不用安裝python了。要想跑python程序,要有解釋器和編譯器。解釋器就是python2或python3含有pythonexe,就是將你編寫的python語言編譯成機器所認識的機器代碼。
python和anaconda的不同點
編譯器就是你寫代碼的環境,比如pycharm或者vscode。由於python3不兼容python2,也就是說python2語言寫出來的代碼沒辦法在python3的環境中運行。那在裝了python3環境的電腦上跑python2怎麼辦呢,也不能每次跑的時候都重新配一下環境變數吧。
也可以但是不覺得麻煩嗎,所以anaconda就誕生了。它可以將每個開發的程序選用不同的環境,而且開發好的程序所需要的環境就是第三方包獨立的打包成來,這樣再在另一台電腦上跑該程序時就不用再單獨下載包了。
H. 再見 requirements.txt,Python 管理依賴項請用 pip
幾年前,當我第一次發現 Python 的 requirements.txt 和虛擬環境時,說實話我感覺真的很棒。
requirements.txt文件是管理依賴項的一種非常有用的方法,但過了一段時間,當你擁有多個子依賴項的依賴項時,開始迷失在它們的關系中。
讓我們通過一個簡單的例子來解釋使用它的主要問題。
你安裝依賴項 F,它恰好具有 G 作為子依賴項。一段時間後,在 requirements.txt 中看到的只是 A、B、C、D、E、F、G、H 作為你的依賴項。
你不知道直接或間接安裝了哪些依賴項,因此現在更新甚至刪除 F 成為一個問題,因為你必須搜索才能知道 G 是作為子依賴項安裝的。即使搜索,可以刪除 G,還是其他包的子依賴項?
最終會留下陳舊的依賴項並堆積垃圾或花費大量時間進行完整搜索並刪除所有未使用的內容。
這不是唯一的問題。如果你不夠小心並且只是為了測試目的而安裝了一個包,那也可能會永遠出現在你項目的依賴項中。
為了解決這個問題,許多聰明人想出了更好的方法來管理 Python 中的依賴項。我們有 pip-tools 和 poetry。
在本文中,我們將分享如何使用 pip-tools 的一個可靠示例,說明如何從項目開始就管理依賴項。
假設我們有一個項目,我們必須在其中使用 Django 和 Pandas。
首先,您需要在您將使用的每個 virtualenv 中安裝 pip-tools,但它就像使用一樣簡單:
現在,我們創建一個 requirements.in 文件,並且只包含我們項目的直接依賴項。每次想要更新或包含依賴項時,你都必須來到這里。它看起來像這樣:
你能看出它與舊的.txt文件有何不同嗎?在這一個中,我們只包括直接依賴項。您可以選擇是否包含版本限制,如下所示:
主要區別在於,這是從現在開始生成你的 requirements.txt 的秘訣。完成創建後,你可以運行以最終編譯需求:
這將在生成 .in 文件的同一文件夾中生成一個 requirements.txt。但是你會發現他們兩個之間有很大的不同。requirements.txt現在通過在它們下面附加該信息來精確控制某個包是否是其他包的子依賴項,如下所示:
就這樣,您消除了之前討論的所有問題。因為你擁有管理包裹所需的所有信息。
除此之外,pip-tools 還提供了其他便利功能,你可以 探索 這些功能以使流程更加輕松。
要升級包,請使用以下命令(以 Django 為例):
這將自動更新你 requirements.txt 文件,包括這些更改。只需記住刪除"小於版本4"的約束以允許它。
為了使你的 virtualenv 與當前的 requirements.txt 文件同步,可以簡單地運行以下命令:
這將安裝、升級或卸載您的 requirements.txt 文件中未包含的任何包。
I. 如何管理python項目
Virtual Environments
首先Python似乎沒有類似Maven/Ant這樣的項目管理工具。那麼當一台機器上有多個python項目,且這些python項目各自有不同的依賴,不想互相干擾時怎麼辦呢?
官方做法是使用Virtual Environments將每個項目互相隔離開。一般情況下,我們使用python解釋器運行python腳本或mole:
>python myScript.py
運行的目錄就是安裝的python解釋器,即python.exe所在的目錄。而Virtual Environments就是給每個項目都生成一個項目獨有的目錄,這個目錄里包含python解釋器,python標准類庫和其他各式各樣的必要文件。這樣每個項目就可以使用不同的解釋器和類庫,且互不幹擾。
創建過程也很簡單。首先找到pyvenv.py所在的目錄,這個文件通常在安裝目錄的自目錄\Tools\scripts下。這是一個生成Virtual Environments的工具。然後運行:
>pyvenv tutorial-env
運行後就會生成一個名為「tutorial-env」的目錄。找到這個目錄,可以發現正如官網所說,這個目錄包含運行python項目所必須的一切文件。使用在各自Virtual Environments目錄里包含的解釋器來運行特定的python項目就可以了。同時,對於那些每個項目使用的特定的依賴(packages或mole),則加入到各自Virtual Environments目錄的類庫子目錄中就可以了。這里需要注意的是。創建完Virtual Environments後,還需要激活。做法很簡單,在上例tutorial-env目錄下執行下的命令即可:
>tutorial-env/Scripts/activate
PIP
PIP是官方提供的安裝python第三方類庫(packages/mole)的工具。它可以去PPI(python packages index)查找或下載第三方類庫。網址是:https://pypi.python.org/pypi
找到上例Virtual Environments目錄下的pip.exe並運行:
>pip install lib_name
即可安裝,其他功能請自行查看手冊。如果是在python的安裝目錄下運行pip,則類庫可以被非Virtual Environments的所有項目使用。PIP安裝的其實是package。
Requirements.txt
在Virtual Environments目錄下運行:
>pip freeze > requirements.txt
可以生產一個當前項目所有依賴類庫及其版本的list文件,文件名就是requirements.txt(當然也可以用別的名字)。文件內容大致如下:
novas==3.1.1.3
numpy==1.9.2
requests==2.7.0
使用requirements.txt的好處就是:
The requirements.txt can then be committed to version control and shipped as part of an application. Users can then install all the necessary packages with 「install -r「:
>pip install -r requirements.txt
這樣就可以方便的管理項目依賴了。如果不使用requirements.txt,直接使用version control存儲Virtual Environments目錄,其他程序員直接下載該目錄就可以開始項目開發的做法也可以。
J. 虛擬環境詳解
假想您有一個應用程序需要版本1的numpy庫,而另一個應用程序需要版本2。如何使用這兩個應用程序呢?2.如果您將所有內容安裝到python3.6的site-packages,很容易出現這樣的情況:您無意中升級了不應該升級的。3.如果要使寫的項目正常運行,其所依賴的第三方庫的版本更改都可能讓這個項目無法正常運行。另外,如果您無法將第三方庫安裝到全局site-packages目錄下,該怎麼辦呢?例如,在共享主機上。
我們必須考慮到這些場景,所以虛擬環境誕生了!它們有自己的安裝目錄,並且不與其他虛擬環境共享庫,每個虛擬環境都是獨立的!
目前,有兩種用於創建python虛擬環境的兩種工具:
1.venv在python3.3及更高版本中默認可用,並將pip和setuptools安裝到創建的虛擬環境中(這種行為只在python3.4及更高版本才會出現)。由於我最近沒有時間,我准備在之後的兩篇文章中介紹pip和setuptools。
2.而virtualenv需要單獨安裝。其在python2.7+和python3.3+中默認可用,pip,setuptools和wheel始終安裝到創建的虛擬環境中(此行為忽略python版本!)
venv模塊支持創建輕量級虛擬環境,該環境具有自己的site-packages,可以選擇與系統site-packages隔離。每個虛擬環境都有自己的python二進制文件(與用於創建此環境的二進制文件的版本相匹配),並且可以在其site-packages中安裝自己的獨立python包。
通過venv命令創建虛擬環境:python3 -m venv /path/virtual/env。運行此命令將創建目標目錄(行為為創建任何尚不存在的父目錄)並創建一個pyvenv.cfg文件,文件中的home指向運行該命令的python的安裝目錄。它還創建一個bin(在Windows上是Scripts)子目錄,其中包含python二進制文件、二進制文件的符號鏈接、副本(平台和參數不同,創建的東西也不同)。它還創建一個最初為空的lib/pythonX.Y/site-packages子目錄(在Windows上,這是Lib/site-packages)。如果指定了現有目錄,則將重新使用現有目錄。
不要雙擊虛擬環境下的python.exe,這樣它會忽略虛擬環境。創建的pyenv.cfg文件中的include-system-site-packages默認為false,如果使用了include-system-site-packages選項,則設置為true。除非給出了--without-pip選項,否則將調用ensurepip將pip引導到虛擬環境中。可以為venv提供多條路勁,在這種情況下,將根據給定的選項在每個提供路勁上創建相同的虛擬環境。創建虛擬環境後,可以使用虛擬環境二進制目錄中的腳本激活虛擬環境。腳本調用是特定於平台的。在Windows下,虛擬環境目錄\Scripts\activate.bat激活虛擬環境。當虛擬環境處於活動狀態時,VIRTUAL_ENV環境變數將設置為虛擬環境的路勁,這可用於檢查是否運行在虛擬環境中。指的注意的是,你不需要特別激活虛擬環境,激活只是將虛擬環境的二進制目錄前置到運行shell的PATH環境變數,以便python調用虛擬環境的python解釋器,你可以運行已安裝的腳本,而無需使用它們的完整路勁。但是,安裝在虛擬環境中的所有腳本都應該可以在不激活它的情況下運行,並自動使用虛擬環境下的python運行。你可以通過在shell中輸入"deactive"命令來停用虛擬環境。
當虛擬環境處於活動狀態(即,虛擬環境的python解釋器正在運行時),屬性sys.prefix和sys.exec_prefix指向虛擬環境的基本目錄。而sys.base_prefix和sys.base_exec_prefix指向用於創建虛擬環境的python安裝目錄。如果虛擬環境未處於活動狀態,則sys.prefix和sys.base_prefix,sys.exec_prefix和sys.base_exec_prefix都指向非虛擬環境的python安裝目錄。安裝到虛擬環境中的腳本有一行"shebang",它指向虛擬環境的python解釋器。這意味著腳本將與該解釋器一起運行,而與PATH的值無關。
可以使用下列API根據需要定製虛擬環境:
venv.EnvBuilder( system_site_packages=False , clear=False , symlinks=False , upgrade=False , with_pip=False , prompt=None , upgrade_deps=False )
system_site_packages:指示系統site_packages是否可供虛擬環境使用。
clear:如果為True,將在創建虛擬環境之前刪除任何現有目標目錄的內容
symlinks:指示是否嘗試對python二進制文件進行符號鏈接而不是復制
upgrade:如果為True,則將更新升級python現有環境,這個選項用於在python已升級到位時使用
with_pip:如果為True,則確保在虛擬環境中安裝pip
prompt:激活虛擬環境後要使用的字元串(默認為None,這意味著將使用環境的目錄名)。如果是".",當前目錄用作提示
upgrade_deps:將基本venv模塊更新到pypi上的最新版本
返回的EnvBuilder對象,有以下方法:
craete(envdir),通過指定要包含虛擬環境的目標目錄,創建虛擬環境。
ensure_directories( env_dir ),創建環境目錄和所有必要的目錄,並返回一個上下文對象,這個上下文對象供其他方法使用。
create_configuration(context),在虛擬環境下創建pyenv.cfg配置文件
setup_python( context ),在虛擬環境下創建python可執行文件的拷貝或符號鏈接,在POSIX系統上,如果python3被使用,創建指向該可執行文件的python和python3符號鏈接(除非它們已經存在)
setup_scripts( context ),將適合平台的激活腳本安裝到虛擬環境中。
upgrade_dependencies( context ),升級虛擬環境中的核心venv依賴項包(當前為pip和setuptools)。
post_setup( context ),可在第三方實現中重寫。以在虛擬環境中預安裝軟體包步驟之後 ,進行自定義的操作
我在想還是先略過他們吧,定製一個venv實在是沒有必要,因為虛擬環境的創建還有一個更強大的工具。
下面我們來介紹venv的幾種命令參數,相信看了前面,現在看到便不會看不懂了!
--system-site-packages,允許虛擬環境訪問系統site-packages目錄
--symlinks,在符號鏈接不是平台的默認操作時,仍然嘗試使用符號鏈接,而不是拷貝
--copies,即使符號鏈接是平台的默認操作,也嘗試使用拷貝
--clear,在創建虛擬環境之前刪除任何現有目標目錄的內容
--upgrade,將虛擬環境下的python可執行文件升級到運行腳本的python版本
--without-pip,不再虛擬環境下安裝或升級pip
--prompt PROMPT,將PROMRT作為此虛擬環境下的提示前綴
--upgrade-deps,升級核心依賴項(pip和setuptools)
virtualenv是一種需要python解釋器才能運行的命令行工具。如果你已經有了python3.5+解釋器,那麼最好使用pipx將virtualenv安裝到一個隔離的環境中(好處:以後您升級virtualenv的時候不會影響到系統的其他部分)
virtualenv有一個基本命令:virtualenv env,virtualenv將創建一個與其版本相同的python虛擬環境,並將虛擬環境安裝到子目錄env中。
virtualenv主要是一個命令行應用程序。它的主要作用是修改命令行中的環境變數以創建一個獨立的python環境,因此你需要一個命令行來運行它。所有選項都有合理的默認值,並且有一個必須的參數(創建的虛擬環境的路勁)。 下面列出了可以傳遞給virtualenv的選項及其默認值和簡短說明。
--version,顯示virtualenv軟體包的版本及其位置,然後退出。
--with-traceback,默認值為False,True的行為:失敗會顯示virtualenv內部的堆棧跟蹤
--read-only-appdata,默認值為False,True的行為:以只讀模式使用appdata文件夾(virtualenv用作緩存的數據文件夾)(不允許寫入操作,寫入操作將失敗並報錯)
--app-data,指定virtualenv用作緩存的數據文件夾
--reset-app-data,默認值為False,True的行為:將appdata文件夾清空
-p,--python:指定virtualenv要安裝的python可執行文件。默認情況下使用安裝環境的python解釋器
--try-first-with:在開始查找之前,請先嘗試這些解釋器
--clear,默認值為False,True的行為:在啟動之前刪除目標目錄
--system-site-packages,默認為False,True的行為:允許虛擬環境訪問系統site-packages目錄
--symlinks,默認為True,True的行為: 嘗試使用symlinks而不是拷貝
--copies,--always-,默認False,True的行為:嘗試使用副本
推薦還是使用默認的吧,除非出現錯誤,可以指定--with-traceback進行錯誤調試。
virtualenv還可以通過查找標准ini配置文件進行配置,ini配置文件具體位置取決於你使用的操作系統, 由platformdirs應用程序配置,可以查看。
虛擬環境就介紹到這里了,虛擬環境的本質就是修改shell的PATH環境變數,如果你有這方面的想法,你也可以編寫一個實現虛擬環境的工具,當然,完全沒有這個必要,真的,沒什麼意思。