Windows 平台的安裝建議


在 Windows 安裝多個版本的 python 你需要注意以下幾點:

  • 使用一致的 '系統安裝' 或者 '用戶安裝'. 也就是第一個版本的 python 你是用 '用戶安裝', 以後就都用 '用戶安裝'. 不要一個是 '系統安裝' 下一個卻是用 '用戶安裝'. (這樣子當 Python 環境出現問題時會比較容易排查)
  • 在可行的狀況下, 盡量是用 '系統安裝'. 除非是要不到系統管理者權限無法進行 '系統安裝', 才改用 '用戶安裝'.
  • 除了最常用的版本之外, 其他的版本不要加進環境變數 PATH 裡 (即安裝時, 第一頁的 Add python 3.x to PATH 不要勾選). 如果已經裝錯了, 可以直接使用 '編輯系統環境變數' 來刪掉它 (一般是有二個 C:\Program Files\Python3x\Scripts\C:\Program Files\Python3x\).
  • 使用時請配合使用 python 虛擬環境 (強列建議), 或者參考以下說明.

最後這個選項是當你自訂了 Python 的安裝路徑, 而且是一個很深的路徑 (長度大於 260 個字元), 那麼你會需要啟用這個選項. 進一步了解這個問題

Python Launcher


Python Launcher 是 Python for Windows 才有的功能.(註一)

Python Launcher 的出現, 讓我們可以不必依賴環境變數 PATH 的設定來簡化 python 執行檔的使用, 同時也簡化了多個版本的 python 同時存在時的管理工作. (試想如果你的系統裡安裝 3 或 4 個 python 時, 你到底要如何指定使用其中一個版本?)

/tmp/phpBUBAa9

Python Launcher 與二個版本的 python

Python Launcher py.exe 是自 Python 3.3 版起, 隨附在 Python for Windows 的一個工具程式.

  • 它會被安裝到 windows 目錄中, 因此使用它不必修改環境變數 PATH(註二).
  • 它是一個 python 的多版本啟動管理程式. 所以它和 python 本身的版本無關 (可以啟動任何版本的 Python), 同時在虛擬環境啟動的狀態下, 還認得啟動的那個虛擬環境.
  • 使用時, 只要直接將原本指令中的 python 改成 py 或者附加版號的 py -3.8 即可.

註一: github 上也有人寫了給 Linux 用的 bash script py, 用法和 windows 的 py.exe 幾乎一致, 需要的就自行取用.

註二: 如果你連第一個安裝的 python 也沒有把它的路徑加到環境變數 PATH 裡, 同時又沒有使用 python venv (或其他類似的) 虛擬環境, 會出現找不到 pip 指令的狀況. 請不必大驚小怪, 只要用 py -m pip 替代 pip 就可以了. 而且進到 python venv 虛擬環境中, pip 指令就會可以使用了, 其實影響真的不大. 如果真的沒有 pip 用不習慣, 建議環境變數 PATH 裡還是加上你最常用的那一版, 也方便其他需要 python.exe 的程式或者批次檔的呼叫. 其他的版本安裝時就可以不必加了.

使用方法


  • 列出可用版本: py -0(註三)
  • 沒有啟動虛擬環境時:

    D:\Works\jupyter>py -0
    Installed Pythons found by py Launcher for Windows
     -3.9-64 *
     -3.8-64
    

    啟動了虛擬環境:

    (myEnv) D:\Works\jupyter>py -0
    Installed Pythons found by py Launcher for Windows
     (venv) *
     -3.9-64
     -3.8-64
    

    上面二個指令輸出中, 有打星號 * 的是 py.exe 的預設使用版本. 所以, 不管是否啟動了 venv 虛擬環境, 你都可以放心大膽的直接用 py 來取代指令中的 python.

  • 指定使用特定版本:
    • 可以指定大版本號即可: 例如:
      py -2 test.py 即是使用 python 2 版 (系統有多個 2 版時, 則預設使用最新的 2 版) 執行 test.py;
      py -3 test.py 則是使用 python 3 版 (系統有多個 3 版時, 則預設使用最新的 3 版) 執行 test.py.
    • 可以指定大版本號加次版號: 例如, python 同時有 3.5 和 3.8 版存在:
      • py -3.5 test.py 是用 3.5 版執行;
      • py -3.8 test.py 則是改用 3.8 版執行.
      注意:它只管到次版號這一層, 我們無法指定再細的版號, 例如: 3.8.2 和 3.8.6 是無法指定的. (有這種需求請改用 python venv 或者 conda)
    • 可以配合 .py 檔檔頭的 hashbang (#!), 或者強制指定 python 版本 (覆蓋 hashbang 設定)
    • 例如: 以下三個測試檔案

      test1.py
      import sys
      print(sys.version)
      
      test2.py
      #! python2
      
      import sys
      print(sys.version)
      
      test3.py
      #! python3
      
      import sys
      print(sys.version)
      
      則以下指令結果如其後的註解
      py test1.py        # 預設使用 python 最新版本
      py test2.py        # 使用 #! 指定 python 版本
      py test3.py        # 使用 #! 指定 python 版本
      
      py -3.7 test1.py   # 強制使用 python 3.7 版
      py -3.8 test2.py   # 強制使用 python 3.8 版, (檔頭的 hashbang 無效)
      py -2   test3.py   # 強制使用最新的 python2, (檔頭的 hashbang 無效)
      
    • 找不到指定版本時, 會提示系統內沒有安裝該版本, 例如:
      Requested Python version (2) is not installed

註三: py.exe 只認得經由 python for windows 安裝程式安裝的 python.exe, 它會在 windows registry 中, 寫入 python 版本及安裝路徑. 實際位置如下段說明.

py.exe如何決定用哪一個版本的 python.exe ?


  • 先確定應該用哪一個版本:

  • 如果使用 py.exe 指令時有指定用哪一個版本, 則直接在找尋指定的版本. 如果沒有指定版本, 則py.exe會先檢查 py.ini 來看看是否有預設指定使用哪一個版本:
    依序是:

    1. 使用者家目錄\AppData\Local\py.ini
    2. %SystemRoot%\py.ini(註四)
    但優先權是 使用者家目錄\AppData\Local\py.ini 比較高 (即: 二者同存在時, 不管各自指定的版本是大或小, 都以 使用者家目錄\AppData\Local\py.ini 裡的設定為預設指定的版本). 如果又沒有 py.ini 則預設使用的版本是由下述的二個 registry 中找到的最高版本中的優先權較高的版本+次版號(註五, 註六).

  • 再找尋所需要的版本

  • 接下來 py.exe 會經由檢查 windows registry 來找尋該版本的 python.exe 的路徑:

    1. 先檢查 HKCU\SOFTWARE\Python\PythonCore\<a>.<b>\InstallPath
    2. 再檢查 HKLM\SOFTWARE\Python\PythonCore\<a>.<b>\InstallPath

    如果 HKCU (登載使用者安裝的版本) 裡有找到需要版本的安裝路徑時, 優先使用 HKCU 裡找到的. 找不到, 再到 HKLM (登載系統安裝的版本) 裡找所需要的版本. 當 HKCUHKLM 裡都有相同的版本+次版號時, HKCU 的優先權大於 HKLM(註六).

註四: %SystemRoot% 的實際位置一般是 C:\Windows

註五: 有點拗口. 應該是沒有指定版本時, 如果 HKCU 裡有找到 python 安裝路徑時, 優先使用 HKCU 裡找到的最大版本. 沒有時, 改用 HKLM 裡找到的最大版本. 二者都有, 當然以 HKCU 優先. 有指定版本時, HKCU 裡有就用 HKCU 裡的, 沒有再改用 HKLM 裡的.

註六: python 的版本號使用 a.b.c 的格式. a 是大版本號用於架構修改, 即所謂的大改版; b 是次版號用於增加新功能/特性時; c 為修正版號用於修正錯誤; 但是 py.exepy.ini 二者都只會看到版本+次版號 (即 a.b) 而不管修正版號. 故而當 py.exe 決定使用 3.8 版時, 即便系統安裝的版本是 3.8.6 系統依然會選擇使用使用者安裝3.8.3 版.

檢查 python 的路徑及版本號碼


出於各種不同的原因, 你可能會有許多的 python 執行環境 (包括: 安裝了多個版本, 並為不同專案建了不同版本的虛擬環境). 因此需要知道並確定當下我們使用的 python.exe 是哪一個, 還有版本是多少?

下列指令可以列出當前環境下你下的 python 指令是哪一個?

# Windows cmd, powershell, git-bash
where python
# 或者 mac OS X, Linux, git-bash (windows)
which python

Windows cmd 及 powershell 視窗會列出所有可以經由環境變數 PATH 找到的 python.exe (當然只有第一個才是真正會被系統叫用的 python.exe). mac 及 linux 則只會輸出第一個經由環境變數 PATH 找到的 python 執行檔. 另外 Windows 的 git-bash 視窗則比較特別: 二者指令都可以用.

如果你是在 jupyter 環境裡, 也可以在 code cell 裡輸入並執行 !where python 或者是 !which python 指令得知目前使用的 python 是安裝在哪一個路徑中.

下列指令可以列出 python 的版本號碼

python --version
# 或者
python -V        # 注意是大寫 V

同樣的, 下列指令可以列出 py.exe 所帶出來的 python 版本號碼

py --version
# 或者
py -V            # 注意以下都是大寫 V
# 或者
py -3 -V         # py 帶出哪一個版本的 python3
# 或者
py -3.8 -V       # py 帶出哪一個版本的 3.8

配合 python venv 模組建立虛擬環境


知道 py.exe 如何運作之後, 我們就可以很容易的建立不同版本的 python 虛擬環境.

D:\ProjA>py -m venv vEnv3           # 使用預設版本, 建立虛擬環境 vEnv3
D:\ProjA>vEnv3\Scripts\activate     # 進入虛擬環境 vEnv3
(vEnv3) D:\ProjA>py -m pip install -U pip   # 更新虛擬環境的 pip
# 可以為 vEnv3 安裝 python package 了
(vEnv3) D:\ProjA>pip install ...

# 或者
D:\ProjA>py -3.9 -m venv vEnv39     # 使用 3.9 版, 建立虛擬環境 vEnv39
D:\ProjA>vEnv39\Scripts\activate    # 進入虛擬環境 vEnv39
(vEnv39) D:\ProjA>py -m pip install -U pip   # 更新虛擬環境的 pip
# 可以為 vEnv39 安裝 python package 了
(vEnv39) D:\ProjA>pip install ...

# 或者
D:\ProjA>py -3.8 -m venv vEnv38     # 使用 3.8 版, 建立虛擬環境 vEnv38
D:\ProjA>vEnv38\Scripts\activate    # 進入虛擬環境 vEnv38
(vEnv38) D:\ProjA>py -m pip install -U pip   # 更新虛擬環境的 pip
# 可以為 vEnv38 安裝 python package 了
(vEnv38) D:\ProjA>pip install ...

為不同版本的 python 安裝 package


也可以利用 py.exe 來為各個版本的 python 安裝 package. 例如: 安裝 jupyterlab 和一些 AI 數據分析常用的套件.

py -3.5 -m pip install jupyterlab numpy pandas matplotlib
py -3.9 -m pip install jupyterlab numpy==1.19.3 pandas matplotlib

注意: 請不要和上面的虛擬環境下用的指令搞混了. 在虛擬環境裡, 其他不相干的 python 環境已經隔開了, 所以我們並不需要再額外指版本. 而是應該啟動該虛擬環境, 再直接用pip install jupyterlab numpy pandas matplotlib 來安裝 package.

如何執行 python file


在 windows 平台上執行 python script 有下列幾個方法 (以 test.py 為例):

  1. windows 視窗下滑鼠雙擊 test.py
  2. 命令提示字元視窗下輸入 python test.py
  3. 命令提示字元視窗下輸入 py test.py
  4. 命令提示字元視窗下輸入 test.py
  • 方法一基本上是一閃就過去了, 所以沒有什麼用. 除非執行的 .py 檔會開啟互動視窗 (或者有 python 的輸入指令, 才會停一下).
  • 方法二是比較通用的方法 (多平台). 但必需將 python 的安裝路徑加入到環境變數 PATH. 如果是在 Linux 平台上, 我們則可以將其中的 python 可以換成 python2, python3 python3.7 等等不同版本的. Windows 平台則必需用方法三.
  • 方法三是 Windows 平台特有的. 用法前面的段落已經說過了不再重複.
  • 方法四雖然也是多平台通用的方法, 但設定及作法有些不同.
    • 在 Windows 上, 是依據 windows registry 的設定決定它的行為. 在安裝了 python3 的情況下在 .py 檔的註冊內容是Python.File; 而 Python.File 內則註冊了 shell/open/command 這個 key, 而它的內容則是 "C:\WINDOWS\py.exe" "%L" %* (python2.7 的內容則是 "C:\Python27\python.exe" "%1" %*, 注意: 如果 python27 比 python3 來得晚安裝, 這一部份會被覆蓋, 請你將它改回來). 所以是等同於使用py.exe 指令.
    • Python.File 的註冊內容

      Python.File 的註冊內容

    • 如果你輸入 test.py 結果是跳出 VS code 視窗, 可以直接找到 VSCode.py 這個註冊位置, 然後直接將它刪除即可.
    • VSCode.py 的註冊內容

      VSCode.py 的註冊內容

    • 在 Linux 平台上的設定由二個部份組成. 首先是 python script 檔要加上 x 權限 (執行權限), 再來還要在 script 檔的第一行加上一個所謂的 shebang(註七) 如下:
      #! /usr/bin/env python
      或者是
      #! /usr/bin/env python3
    • 如果 script 是 python2 的版本請用第一個 python, python3 的 script 則請用第二個 python3. 當然如果需要指定 python 的次版本也是可以的, 如: /usr/bin/env python3.8.
    • 同時建議你用 /usr/bin/env 指令來帶動 pythonpython3, 而不是直接使用 /usr/bin/python. 二者的差異在 env 指令是由環境變數 PATH 中找後面的 pythonpython3, 而不是直接使用絕對路徑來指定 pythonpython3 的路徑(註八).
    • 這個 shebang 設定在 Windows 平台上也相容, 同時動作也是一致的.(註九)

註七: shebanghashbang 的另一稱呼. 參考維基百科 https://zh.wikipedia.org/wiki/Shebang

註八: 參考 StackExchange why do some python scripts begin with #!/usr/bin/env python?

註九: 在 Windows 平台上, shebang 的行為也一樣受 windows registry 控制. 如果你在安裝 Python 2.7.18 時取消第一個選項 'Register Extensions', 那麼下面的 shebang 設定
#! /usr/bin/env python
或者
#! /usr/bin/python
依然可以是使用 python3 執行. 至於安裝 Python 2.7 時沒有修改預設行為的可以考慮將 Python 2.7 解安裝再重新安裝. 至於到底是哪一個 registry 控制它要再等等 (需要一點時間實驗).

相關文章連結


    MagicJackTing 發表在 痞客邦 留言(6) 人氣()