안녕하세요. 제 이름은 somenzz입니다. Zheng 형제라고 불러도 됩니다.
Python의 가져오기는 매우 직관적이지만 그럼에도 불구하고 패키지가 분명히 있음에도 불구하고 상대 경로가 매우 정확하더라도 모듈을 가져올 때 오류가 보고되는 경우가 있습니다.
ImportError: attempted relative import with no known parent package
동일한 디렉터리에 있는 모듈은 서로 완전히 다릅니다. 이 기사에서는 가져오기를 쉽게 처리할 수 있도록 가져오기를 사용할 때 자주 발생하는 몇 가지 문제를 분석합니다. 이를 기반으로 자신만의 패키지를 쉽게 만들 수 있습니다.
모듈과 패키지의 관계는 파일과 디렉터리에 비유할 수 있습니다.
Python 문서에서는 Python 파일이 모듈이고 Python 파일 이름(접미사 .py 제외)이 모듈 이름이라고 설명합니다.
모듈에는 모듈에서 정의한 네임스페이스의 일부인 변수, 함수 및 클래스가 포함될 수 있으므로 두 개의 다른 모듈이 동일한 이름의 변수, 함수 및 클래스를 가질 수 있으므로 변수 이름 지정은 문제가 되지 않습니다.
모듈과 패키지의 관계는 파일과 디렉터리에 비유할 수 있습니다.
패키지는 모듈이나 하위 패키지를 포함할 수 있습니다. 모듈은 변수, 함수 및 클래스가 두 개의 서로 다른 모듈에서 동일한 이름을 가질 수 있도록 네임스페이스를 정의합니다. 마찬가지로 패키지는 해당 구성 요소 패키지 및 모듈에 대해 동일한 작업을 수행합니다. .
기본 패키지에는 하위 패키지, 모듈, __init__.py(Python 3.3 이후에는 필요하지 않음), setup.py가 포함될 수 있습니다. 가능한 패키지 구조는 다음과 같습니다.
setup.py는 패키지가 있는 홈 디렉터리에 존재하며 필수 종속성, 스크립트 및 하위 패키지와 같은 구성 정보를 포함합니다. 패키지 이름, 작성자, 설명 등과 같은 패키지에 대한 메타데이터를 지정할 수도 있습니다.
setup.py는 pip가 패키지를 설치하는 데 사용하는 파일입니다.
먼저 간단한 예를 들어보겠습니다. 동일한 디렉터리에 file1.py와 file2.py라는 두 개의 파일이 있습니다. 내용은 매우 간단합니다. 차이점은 File1을 file2.py에서 가져옵니다.
#file1.py print("This is file1.py") #file2.py print("This is file2.py") import file1
file2.py를 실행하면 다음과 같은 결과를 얻을 수 있습니다.
❯ python file2.py This is file2.py This is file1.py
볼 수 있습니다.
import의 검색 순서도 알아야 합니다. 한 가지만 기억하세요. 즉, import는 sys.path에서 검색한다는 것입니다.
예를 들어 file2.py 끝에 import sys; print(sys.path) 코드 한 줄을 추가하면 import 검색 경로가 인쇄될 수 있습니다.
다음 순서를 볼 수 있습니다. sys.path:
sys.path에 대해 주의해야 할 사항은 다음과 같습니다.
모듈이나 패키지가 발견되면 실행됩니다. 패키지에 초기화 파일 __init__.py가 있으면 import 시 __init__.py가 먼저 실행됩니다.
그러면 가져올 프로젝트가 해당 네임스페이스에 추가되고 xx.yy를 통해 사용할 수 있습니다.
절대 가져오기가 무엇인지 먼저 살펴보겠습니다.
import aa import aa.bb from aa import bb
이 방법은 sys로 이동합니다. .path를 검색합니다. ModuleNotFoundError가 발생하는 경우 sys.path에 가져오려는 패키지가 없는 이유를 생각해 보거나 이 패키지의 경로를 sys.path에 수동으로 삽입하세요.
상대 가져오기가 무엇인지 살펴보겠습니다.
from . import aa from .aa import bb from .. import yy
즉, 상대 경로에 . 가져온 패키지 또는 현재 패키지.
예를 들어 pythonimportexample 디렉터리 아래에 새 디렉터리 subpackage1을 만들고 subpackage1에 두 개의 새 파일 file3.py 및 file4.py를 만듭니다.
내용은 다음과 같습니다.
file3.py :
print("This is file3.py")
file4.py :
from . import file3 print("This is file4.py")
只要我们直接运行 file4.py,那是一定会报错的:
Python 提示我们:
ImportError: attempted relative import with no known parent package
也就是说相对导入不知道父包是谁,换句话说,这是一个子包,必须让父包来调用它,直接运行这个文件是不行的,即使你在 file4.py 的目录 subpackage1 同级的目录执行该文件也是不行的,见上图。
但是在 file4.py 的目录 subpackage1 同级的目录作为一个 module 来执行是可以的,如下图:
换句话说,我们把 subpackage1 作为一个包来让别人用,相对导入是可以的,比如说我们在目录 subpackage1 同级的目录新建一个 file5.py 的文件,内容如下:
file5.py:
from subpackage1 import file4。
然后,执行 python file5.py 可以看出,相对导入已经正常工作:
结论
先上一个图来看下目录及引用结构,方块的是目录,椭圆的是文件,曲线是引用:
其中 import_example 目录下有 setup.py 和 run.py
run.py 导入了 file4、file5、file6。
file4 导入了 file3,file5 导入了 file3。
file6 导入了 file2,file2 导入了 file1。
现在我们来执行一下 run.py 看下效果:
可以看出所有相对导入都已正常工作,虽然 file3 被导入了两次,但只执行了一次,说明 Python 内部已经考虑了同一个包的多重导入问题。
自定义包就是让其他文件导入使用的,因此 pythonimportexample目录下都使用相对导入,源代码见:
https://gitee.com/somenzz/code-example/tree/master/import_example
点阅读原文也可以直接访问。
这里还有一些自定义包的例子:
本文分享了什么是模块(module),什么是包(package),import 的搜索路径,也分享了相对导入和绝对导入的区别,最后举了一个非常实用的 import 例子,方便你构建自己的包。
위 내용은 Python의 가져오기는 어떻게 작동하나요?의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!