Skip to content

如何管理 python 模組

Tsung-Jung Tsai (TJ_Tsai) edited this page Jan 14, 2021 · 21 revisions

在 Python 2.4 實做了 PEP 328 的最簡單部份: 透過 from ... import ... 敘述匯入的模組,從一個模組所匯入的名稱可以使用括號來圍起來,從而更容易匯入許多不同的名稱。

在 Python 2.5 中已經實作了更複雜的部份:可以指定使用「絕對」或「相對於套件」的匯入敘述來匯入一個模組。 在 Python 未來版本中,該計畫將使用絕對匯入作為預設

假設你有像這樣的模組目錄:

A
├── B
│   ├── C.py
│   └── D.py
├── E.py
└── F
    └── G.py

在 A.B.C 模組中,要匯入 D, E, G 的相對作法可以這麽做:

from . import D                 # Imports A.B.D
from .. import E                # Imports A.E
from ..F import G               # Imports A.F.G

前導點不能跟匯入敘述的 import modname 形式一起使用,只允許 from ... import 這種形式



如何使用「絕對」參考

假設你有像這樣的模組目錄:

A
├── B
│   ├── C.py  <--- C.py 想要存取 G.py,要如何匯入 G.py?
│   └── D.py
├── E.py
└── F
    └── G.py

C.py

import sys
root = "/path_to_your_application"
sys.path.append(root + "/A/F")

import G

G.py

print('Hello, G!')

執行結果:

/path_to_your_application$ tree
.
└── A
    ├── B
    │   ├── C.py
    │   ├── D.py
    │   └── __init__.py
    ├── E.py
    ├── F
    │   ├── G.py
    │   └── __init__.py
    └── __init__.py

/path_to_your_application$ python
>>> from A.B import C
Hello, G!




如何將模組的根目錄位置,自動加到系統模組清單?

  • 模組 A 底下的檔案,如果有參考到其他檔案,都要去處理 sys.path.append(...)
  • 模組 A 底下的檔案,若要變更位置,如 A/F/G.py 搬到 A/G.py,就要重新評估相對位置

上面的問題,似乎麻煩了些 有沒有辦法一起參考「模組A」的根目錄?

假設你有像這樣的模組目錄:

A
├── B
│   ├── C.py  <--- C.py 想要存取 G.py,要如何匯入 G.py?
│   └── D.py
├── E.py
└── F
    └── G.py

目錄 A 底下的 __init__.py

# coding=utf8
# 在初始化模組 A 的時候,自動把當前路徑 加到系統模組清單
# 所以,不管使用 C or G,都會經過「模組A」的 __init__.py

import sys
import os

# [debug][start]
cwd = os.getcwd() # current working directory, where you run python
A__init__py_path = __file__
A_path = os.path.join(A__init__py_path, os.pardir)
A_parent_path = os.path.join(A_path, os.pardir)

print("                cwd: " + cwd)
print("path(A/__init__.py): " + A__init__py_path)
print("            path(A): " + A_path)
print("         path(../A): " + A_parent_path)
print("         path(../A): " + os.path.abspath(A_parent_path))
# [debug][end]


# gets the root path of the library
lib_root_path = os.path.abspath(
        os.path.join(
                os.path.join(__file__, os.pardir), 
                os.pardir))

# avoid from adding twice
if lib_root_path not in sys.path:
    sys.path.append(lib_root_path)
    
print("import A, Done!")
print(sys.path)

C.py

from A.F import G

G.showInfo()

G.py

print('import G!')
def showInfo():
    print('Hello, G!')

執行結果:

/path_to_your_application$ tree
.
└── A
    ├── B
    │   ├── C.py
    │   ├── D.py
    │   └── __init__.py
    ├── E.py
    ├── F
    │   ├── G.py
    │   └── __init__.py
    └── __init__.py

/path_to_your_application$ python
>>> from A.B import C
import A, Done!
...
import G!
Hello, G!

不管你是在 test1/Atest1 底下執行 python
還是在 test1/test2/test3/Atest1 底下執行 python
都可以讓 C.py 正確無誤地匯入 G.py



Clone this wiki locally