ImportError: attempted relative import with no known parent package


python中的relative import使用起來卻有不少問題。

比如下面這樣一個結構

crawler
|_src_
 |    |_spiders_
 |             |_test.py
 |
 |_local_settings.py

 

test.py中想import local_settings這個模塊,那在test.py中加上

import ...local_settings

運行 python test.py。 結果就是報了標題的錯誤。

查閱了一些資料,原因如下:

在python文檔https://docs.python.org/3.9/tutorial/modules.html#intra-package-references中有段話:

Note that relative imports are based on the name of the current module. Since the name of the main module is always "main", modules intended for use as the main module of a Python application must always use absolute imports.

還有在PEP 328(https://peps.python.org/pep-0328/#relative-imports-and-name)有:

Relative imports use a module's name attribute to determine that module's position in the package hierarchy. If the module's name does not contain any package information (e.g. it is set to 'main') then relative imports are resolved as if the module were a top level module, regardless of where the module is actually located on the file system.

也就是說由於test.py中的__name__ attribute沒有設置,__name__ == __main__,所以把test.py當成了頂層,這時reletive import就沒法使用了。

解決方法有一:

sys.path.append("../..")

from local_setting import *

二:

不是直接運行test.py這個script,而是當作module來運行

python -m crawler.src.spiders.test

 三:

 不能從頂級模塊中的py中使用relieve import,在 https://docs.python.org/3/tutorial/modules.html#packages中有

 Note that relative imports are based on the name of the current module. Since the name of the main module is always "__main__", modules intended for use as the main module of a Python application must always use absolute imports.

請注意,相對導入是基於當前模塊的名稱。由於主模塊的名稱始終是"__main__",所以要作為 Python 應用程序主模塊使用的模塊必須始終使用絕對導入。

具體的分析過程參照:

https://stackoverflow.com/questions/30669474/beyond-top-level-package-error-in-relative-import

https://stackoverflow.com/questions/14132789/relative-imports-for-the-billionth-time/14132912#14132912

https://stackoverflow.com/questions/16981921/relative-imports-in-python-3

https://stackoverflow.com/questions/68960171/python-error-importerror-attempted-relative-import-with-no-known-parent-package

https://napuzba.com/a/import-error-relative-no-parent/

==============

在bypy項目下直接運行python bypy.py,也直接報這個錯

(venv) (base) gaoxianghu@gaoxiangs-MacBook-Pro bypy % python ./bypy/bypy.py
__file__=/Users/gaoxianghu/git/bypy/bypy/struct.py | __name__=struct               | __package__=                    
Traceback (most recent call last):
  File "./bypy/bypy.py", line 65, in <module>
    import pickle
  File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/pickle.py", line 33, in <module>
    from struct import pack, unpack
  File "/Users/gaoxianghu/git/bypy/bypy/struct.py", line 11, in <module>
    from .util import iswindows
ImportError: attempted relative import with no known parent package
print('__file__={0:<35} | __name__={1:<20} | __package__={2:<20}'.format(__file__,__name__,str(__package__)))

可以看到__name__=struct,__package__沒有信息,因為name里沒有包含‘.’,表示不在package里,relative import只能用在package里,所以報:

attempted relative import with no known parent package

 However, if your module's name is __main__, it is not considered to be in a package. Its name has no dots, and therefore you cannot use from .. import statements inside it. If you try to do so, you will get the "relative-import in non-package" error.

Scripts can't import relative

What you probably did is you tried to run moduleX or the like from the command line. When you did this, its name was set to __main__, which means that relative imports within it will fail, because its name does not reveal that it is in a package.

 

讓我們看看python解釋器是如何解析相關模塊。從 PEP 328 中,我們找到了關於 the relative imports(相對引用)的介紹:

Relative imports use a module’s __name__ attribute to determine that module’s position in the package hierarchy. If the module’s name does not contain any package information (e.g. it is set to __main__ ) then relative imports are resolved as if the module were a top level module, regardless of where the module is actually located on the file system.

相對導入通過使用模塊的 __name__ 屬性來確定模塊在包層次結構中的位置。如果該模塊的名稱不包含任何包信息(例如,它被設置為 __main__ ),那么相對引用會認為這個模塊就是頂級模塊,而不管模塊在文件系統上的實際位置。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM