python-3.x matplotlib文字 - Python 3中的相對導入





python用法 matplotlib放大 (7)


如果兩個軟件包都在你的導入路徑(sys.path)中,並且你想要的模塊/類在example / example.py中,那麼訪問這個類時不需要相對導入try:

from example.example import fkt

我想從同一個目錄中的另一個文件導入一個函數。

有時它適用於我from .mymodule import myfunction但有時我得到一個:

SystemError: Parent module '' not loaded, cannot perform relative import

有時它與from mymodule import myfunction ,但有時我也會得到一個:

SystemError: Parent module '' not loaded, cannot perform relative import

我不明白這裡的邏輯,我找不到任何解釋。 這看起來完全隨機。

有人可以向我解釋這一切背後的邏輯是什麼?




我遇到了這個問題。 黑客解決方法是通過if / else塊導入,如下所示:

#!/usr/bin/env python3
#myothermodule

if __name__ == '__main__':
    from mymodule import as_int
else:
    from .mymodule import as_int


# Exported function
def add(a, b):
    return as_int(a) + as_int(b)

# Test function for module  
def _test():
    assert add('1', '1') == 2

if __name__ == '__main__':
    _test()



希望這對那裡的人有價值 - 我經歷了半打的帖子,試圖找出類似於上面發布的內容的相對導入。 我按照建議設置了一切,但是我仍然碰到了ModuleNotFoundError: No module named 'my_module_name'

由於我只是在本地開發和玩耍,所以我沒有創建/運行setup.py文件。 我也沒有明確設置我的PYTHONPATH

我意識到當我像我一直在測試與模塊在同一目錄中一樣運行我的代碼時,我找不到我的模塊:

$ python3 test/my_module/module_test.py                                                                                                               2.4.0
Traceback (most recent call last):
  File "test/my_module/module_test.py", line 6, in <module>
    from my_module.module import *
ModuleNotFoundError: No module named 'my_module'

但是,當我明確指定路徑的事情開始起作用時:

$ PYTHONPATH=. python3 test/my_module/module_test.py                                                                                                  2.4.0
...........
----------------------------------------------------------------------
Ran 11 tests in 0.001s

OK

因此,如果有人嘗試了一些建議,相信他們的代碼結構正確,並且如果您不將當前目錄導出到您的PYTHONPATH,仍然會發現自己處於與我嘗試以下任一情況類似的情況:

  1. 運行你的代碼並顯式包含如下所示的路徑: $ PYTHONPATH=. python3 test/my_module/module_test.py $ PYTHONPATH=. python3 test/my_module/module_test.py
  2. 避免調用PYTHONPATH=. ,創建一個setup.py文件,其內容如下所示,並運行python setup.py development以將包添加到路徑中:
# setup.py
from setuptools import setup, find_packages

setup(
    name='sample',
    packages=find_packages()
)



把它放在包的__init__.py文件中

import os, sys
#For relative imports to work in Python 3.6
sys.path.append(os.path.dirname(os.path.realpath(__file__)))

假設你的軟件包是這樣的:

    .
├── project
│   ├── package
│   │   ├── __init__.py
│   │   ├── module1.py
│   │   └── module2.py
│   └── setup.py

現在在你的包中使用常規導入,如:

#in module2.py
from module1 import class1

這適用於Python 2和Python 3




不幸的是,這個模塊需要放在包裡面,有時候它也需要作為腳本運行。 任何想法我怎麼能實現呢?

有這樣的佈局是很常見的...

main.py
mypackage/
    __init__.py
    mymodule.py
    myothermodule.py

...像這樣的mymodule.py ...

#!/usr/bin/env python3

# Exported function
def as_int(a):
    return int(a)

# Test function for module  
def _test():
    assert as_int('1') == 1

if __name__ == '__main__':
    _test()

...這樣的myothermodule.py ...

#!/usr/bin/env python3

from .mymodule import as_int

# Exported function
def add(a, b):
    return as_int(a) + as_int(b)

# Test function for module  
def _test():
    assert add('1', '1') == 2

if __name__ == '__main__':
    _test()

...和這樣一個main.py ...

#!/usr/bin/env python3

from mypackage.myothermodule import add

def main():
    print(add('1', '1'))

if __name__ == '__main__':
    main()

...運行main.pymypackage/mymodule.py時工作正常,但由於相對導入而失敗mypackage/myothermodule.py ...

from .mymodule import as_int

你應該運行它的方式是......

python3 -m mypackage.myothermodule

...但它有點冗長,並且不能與像#!/usr/bin/env python3這樣的shebang線混合。

假設名稱mymodule是全局唯一的,這種情況下最簡單的解決方法是避免使用相對導入,並使用...

from mymodule import as_int

...雖然,如果它不是唯一的,或者你的包結構更複雜,你需要在PYTHONPATH包含你的包目錄的目錄,並像這樣做...

from mypackage.mymodule import as_int

...或者如果你希望它能“開箱即用”,那麼你可以首先用代碼來擦掉PYTHONPATH ...

import sys
import os

PACKAGE_PARENT = '..'
SCRIPT_DIR = os.path.dirname(os.path.realpath(os.path.join(os.getcwd(), os.path.expanduser(__file__))))
sys.path.append(os.path.normpath(os.path.join(SCRIPT_DIR, PACKAGE_PARENT)))

from mypackage.mymodule import as_int

這是一種痛苦,但是為什麼在某個Guido van Rossum寫的電子郵件中有一條線索......

我對此和任何其他提議的__main__機器的__main__都是-1。 唯一的用例似乎是運行恰好在模塊目錄內的腳本,我一直認為這是一個反模式。 為了讓我改變主意,你必須說服我,它不是。

無論是在一個包中運行腳本是否為反模式都是主觀的,但是我個人發現它在包含一些自定義wxPython小部件的包中非常有用,所以我可以運行任何源文件的腳本來顯示wx.Frame僅包含該小部件的wx.Frame用於測試目的。




為了避免這個問題,我設計了一個解決方案,這個解決方案已經為我工作了一段時間。 它將上層目錄添加到lib路徑中:

import repackage
repackage.up()
from mypackage.mymodule import myfunction

通過智能策略(檢查調用堆棧),重新打包可以使各種情況下的相關導入工作。




str - 從給定對象創建新的字符串對象。

repr - 返回對象的規範字符串表示形式。

差異:

STR():

  • 使對象可讀
  • 為最終用戶生成輸出

再版():

  • 需要復制對象的代碼
  • 為開發人員生成輸出




python python-3.x python-import