python3을 사용하여 jupyter 노트북의 상대 가져 오기와 함께 다른 디렉토리에있는 모듈에서 로컬 함수 가져 오기
다음과 유사한 디렉토리 구조가 있습니다.
meta_project
project1
__init__.py
lib
module.py
__init__.py
notebook_folder
notebook.jpynb
작업 할 때 notebook.jpynb
상대 가져 오기를 사용하여 함수 function()
에 액세스하려고 할 때 module.py
:
from ..project1.lib.module import function
다음과 같은 오류가 발생합니다.
SystemError Traceback (most recent call last)
<ipython-input-7-6393744d93ab> in <module>()
----> 1 from ..project1.lib.module import function
SystemError: Parent module '' not loaded, cannot perform relative import
상대 가져 오기를 사용하여 작동하도록하는 방법이 있습니까?
노트북 서버는 meta_project
디렉토리 수준에서 인스턴스화 되므로 해당 파일의 정보에 액세스 할 수 있어야합니다.
또한 최소한 원래 의도 한대로 project1
모듈로 생각되지 않았으므로 __init__.py
파일 이 없으며 파일 시스템 디렉토리로만 의미됩니다. 문제를 해결하기 위해 모듈로 처리하고 __init__.py
파일 (빈 파일 포함)을 포함해야하는 경우 괜찮지 만 그렇게하는 것만으로는 문제를 해결할 수 없습니다.
이 디렉토리를 머신간에 공유하고 상대 가져 오기를 통해 모든 곳에서 동일한 코드를 사용할 수 있으며 빠른 프로토 타이핑을 위해 노트북을 자주 사용하므로 절대 경로를 함께 해킹하는 제안은 도움이되지 않을 것입니다.
편집 : 이것은 일반적으로 Python 3의 상대적 가져 오기, 특히 패키지 디렉토리 내에서 스크립트 실행에 대해 말하는 Python 3의 상대 가져 오기 와는 다릅니다 . 이것은 일반적인 측면과 특정 측면이 모두 다른 다른 디렉토리의 로컬 모듈에서 함수를 호출하려는 jupyter 노트북 내에서 작업하는 것과 관련이 있습니다.
인접한 모듈의 기능을 DRY 방식으로 사용하는 방법을 설명하고자하는 이 노트북 에서 여러분과 거의 같은 예를 들었습니다 .
내 솔루션은 노트북에 다음과 같은 코드 조각을 추가하여 Python에 추가 모듈 가져 오기 경로를 알리는 것입니다.
import os
import sys
module_path = os.path.abspath(os.path.join('..'))
if module_path not in sys.path:
sys.path.append(module_path)
이를 통해 모듈 계층에서 원하는 함수를 가져올 수 있습니다.
from project1.lib.module import function
# use the function normally
function(...)
비어있는 __init__.py
파일이 아직없는 경우 project1 / 및 lib / 폴더 에 추가 해야합니다.
노트북에서 작업 할 때 코드를 하위 모듈로 추상화하는 모범 사례를 찾고 있습니다. 모범 사례가 있는지 잘 모르겠습니다. 나는 이것을 제안하고있다.
다음과 같은 프로젝트 계층 구조 :
├── ipynb
│ ├── 20170609-Examine_Database_Requirements.ipynb
│ └── 20170609-Initial_Database_Connection.ipynb
└── lib
├── __init__.py
└── postgres.py
그리고 20170609-Initial_Database_Connection.ipynb
:
In [1]: cd ..
In [2]: from lib.postgres import database_connection
이는 기본적으로 Jupyter Notebook이 cd
명령을 구문 분석 할 수 있기 때문에 작동합니다 . 이것은 Python Notebook 마법을 사용하지 않습니다. 그것은 단순히 접두사없이 작동합니다 %bash
.
Project Jupyter Docker 이미지 중 하나를 사용하여 Docker에서 작업하고있는 100 번 중 99 번을 고려 하면 다음 수정 은 멱등 적입니다.
In [1]: cd /home/jovyan
In [2]: from lib.postgres import database_connection
So far, the accepted answer has worked best for me. However, my concern has always been that there is a likely scenario where I might refactor the notebooks
directory into subdirectories, requiring to change the module_path
in every notebook. I decided to add a python file within each notebook directory to import the required modules.
Thus, having the following project structure:
project
|__notebooks
|__explore
|__ notebook1.ipynb
|__ notebook2.ipynb
|__ project_path.py
|__ explain
|__notebook1.ipynb
|__project_path.py
|__lib
|__ __init__.py
|__ module.py
I added the file project_path.py
in each notebook subdirectory (notebooks/explore
and notebooks/explain
). This file contains the code for relative imports (from @metakermit):
import sys
import os
module_path = os.path.abspath(os.path.join(os.pardir, os.pardir))
if module_path not in sys.path:
sys.path.append(module_path)
This way, I just need to do relative imports within the project_path.py
file, and not in the notebooks. The notebooks files would then just need to import project_path
before importing lib
. For example in 0.0-notebook.ipynb
:
import project_path
import lib
The caveat here is that reversing the imports would not work. THIS DOES NOT WORK:
import lib
import project_path
Thus care must be taken during imports.
'program tip' 카테고리의 다른 글
숨겨진 파일이없는 cp -r (0) | 2020.10.10 |
---|---|
adb shell을 사용하여 안드로이드 폰의 모든 파일을 나열하는 방법은 무엇입니까? (0) | 2020.10.10 |
임시 솔루션이 영원히 지속되는 것을 어떻게 막습니까? (0) | 2020.10.10 |
HttpWebRequest.GetResponse () 실패시 오류 정보를 얻는 방법 (0) | 2020.10.10 |
제네릭 클래스의 기본 생성자 구문은 무엇입니까? (0) | 2020.10.10 |