簡體   English   中英

Python - ModuleNotFoundError:沒有模塊命名

[英]Python - ModuleNotFoundError: No module named

我是 Python 的新手,我在這個簡單的示例中遇到以下錯誤:

這是我的項目結構:

python_project
.
├── lib
│   ├── __init__.py
│   └── my_custom_lib.py
└── src
    ├── __init__.py
    └── main.py

這是我執行src/main.py文件時的錯誤:

☁  python_project  python src/main.py

Traceback (most recent call last):
  File "src/main.py", line 3, in <module>
    from lib import my_custom_lib
ImportError: No module named lib

如果我將main.py文件移動到根目錄,然后再次執行此文件,則可以工作...但在src/目錄中不起作用

這是我的main.py

from lib import my_custom_lib

def do_something(message):
        my_custom_lib.show(message)

do_something('Hello World!')

注意:當我從Pycharm執行相同的代碼時工作正常,但不是從我的終端。

您的PYTHONPATH設置為您執行的程序的當前目錄。 因此,如果您在目錄src中執行某些操作,它將永遠無法找到目錄lib ,因為它位於路徑之外。 有幾個選擇;

  • 如果它屬於您的代碼,只需將lib/移動到src/中。 如果是外部 package,則應按照 Henrique Branco 所述安裝 pip。
  • src/之外有一個頂級腳本,用於導入和運行src.main 這會將頂級目錄添加到 python 路徑。
  • src/main.py修改sys.path以包含頂級目錄。 這通常是不受歡迎的。
  • 使用python -m src.mainsrc/main.py作為模塊調用,這會將頂級目錄添加到 python 路徑。 輸入有點煩人,而且您需要更改所有導入。

如果我可以添加到MarkM 的答案中,如果您想保留當前目錄結構並使其正常工作,您可以在根目錄中添加setup.py ,您可以在其中使用setuptools創建可以安裝的 package。

如果您的文件包含以下內容:

# setup.py

from setuptools import find_packages, setup

setup(
  name='foo',
  version=`1.0.0`,
  packages=find_packages(),
  entrypoints={
    'console_scripts': [
      'foo=src.main:main',
    ],
  },
)

然后你做pip install [--user] -e path/to/directory你會得到一個“可編輯的包”,它將有效地成為你開發目錄中 package 的符號鏈接,所以你所做的任何更改都不需要重新安裝(當然,除非您重新調整 package 結構或添加/刪除/編輯入口點)。

這確實假設您的src/main.py有一個主要的 function。

即使在 Python3 中,您的“包”目錄中也需要__init__.py文件,否則 Python 會假定這些是命名空間包(不會詳細介紹 go)並且find_packages()調用不會找到它們。

這也將允許您的相對導入工作。 絕對導入僅在從入口點調用腳本時有效,但在直接在開發目錄中調用腳本時無效。

您錯誤地使用了from a import b 它應該是這樣的:

import lib.my_custom_lib

另一種方法用於從模塊中導入某些方法、函數和類,而不是模塊本身。 要從 my_custom_lib 模塊導入特定的 function,它看起來像這樣:

from lib.my_custom_lib import foo

嘗試使用相對導入:

from..lib import my_custom_lib

你的 main.py 腳本應該在你的目錄結構中的所有 python 包之上。 嘗試將您的項目更新為以下結構:

.
|__ main.py
|__ lib
|   |__ __init__.py
|   |__ your_custom_lib.py
|__ another_python_package
    |__ __init__.py
    |__ another_python_scripts

之后,您的項目目錄中的python main.py將起作用。

在我的情況下,第 1 行的可視代碼實際錯誤

我沒有導入 _typeshed 模塊,但默認情況下它是他們的,所以如果您在第 1 行中找到,請刪除該模塊

MarkM 的回答還是很出色的; 我現在正在使用 PyPi。 我試圖消除他所說的“當前目錄”的歧義。 如果我的困惑是一個預期的功能,我就是這樣做的。

vagrant@testrunner:~/pypath$ tree
.
├── proga
│   └── script1.py
└── progb
    └── script1.py

script1.py 在兩個目錄中是相同的:

#!/usr/bin/env python3
import sys
print(sys.path)

哪里運行它沒有區別, PYTHONPATH在包含我指定的腳本的目錄之前添加:

vagrant@testrunner:~/pypath/proga$ ./script1.py 
['/home/vagrant/pypath/proga', '/usr/lib/python38.zip', '/usr/lib/python3.8', '/usr/lib/python3.8/lib-dynload', '/home/vagrant/.local/lib/python3.8/site-packages', '/usr/local/lib/python3.8/dist-packages', '/usr/lib/python3/dist-packages']
vagrant@testrunner:~/pypath/proga$ ../progb/script1.py 
['/home/vagrant/pypath/progb', '/usr/lib/python38.zip', '/usr/lib/python3.8', '/usr/lib/python3.8/lib-dynload', '/home/vagrant/.local/lib/python3.8/site-packages', '/usr/local/lib/python3.8/dist-packages', '/usr/lib/python3/dist-packages']

對我來說,在這種情況下使用顯式路徑導入效果最好。 如果您需要 go 在樹中使用“..”。 管道有點麻煩,但它總是有效的。

path = os.path.abspath(os.path.join(pathlib.Path(__file__).parent.absolute(), '..', 'subdir', 'myFile.py'))
loader = importlib.machinery.SourceFileLoader('myFile', path)
spec = importlib.util.spec_from_loader('myFile', loader)
module = importlib.util.module_from_spec(spec)
spec.loader.exec_module(module)

# now use the module:
module.myMethod()
myClassInstance = module.myClass()

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM