파이썬 import에서 상대 경로, 절대 경로에 의한 참조 알고 있다고 가정한다. 

 

해당 글은 vscode에서 다른 디렉토리의 모듈을 불러올 때 sys.append()을 사용하기 싫은데 참조할만한 글이 sys.append()를 사용하는 경우만 있었던 상황을 위해 작성한 글이다.

 

문제상황

결론부터 얘기하자면, pycharm에서 모듈참조를 할 때 절대 경로로 참조를 하면 문제가 생기지 않는다. 하지만 vscode에서 참조를 할 때는 문제가 발생하는데, 이는 vscode에서 자동으로 PYTHONPATH에 실행할 workspacefoler의 경로를 추가해주지 않기 때문이다. (실행되는 .py파일이 디렉토리의 최상단 구조라면 문제는 발생하지 않는다.)

 

파이썬에서 import문을 통해 다른 모듈을 불러올 때 내부적으로 파일을 찾기 위해 파일을 탐색하는 순서는 다음과 같다.

  1. sys.modules
  2. built-in modules
  3. sys.path

PYTHONPATH 환경 변수에 경로를 추가하면, 파이썬은 내부적으로 PYTHONPATH에 등록된 경로들을 sys.path에 추가해준다. 즉, sys.append()코드를 사용하여 모듈을 불러올 위치를 load하는 것으로 자동으로 sys.append()를 해주는 효과를 볼 수 있다.

 

 

문제 상황 재현

ddpm/ 디렉토리에 존재하는 import_test.py에서 dataset_class/ 디렉토리의 duke_dataset.py 모듈에 접근할 때 ModuleNotFoundError 오류가 발생한다.

 

전체 디렉토리 구조는 다음과 같다.

/workspace/Model_Implementation
|-- CNN/
|   |-- Lenet/
|   |   |-- model.py
|   |   `-- train.py
|   `-- Resnet18/
|       |-- DukeClassification/
|       |   |-- dataset/
|       |   |   `-- duke_breast_ataset.py
|       |   |-- model/
|       |   |   `-- Resnet18.py
|       |   `-- train/
|       |       `-- train.py
|       `-- ResNet18_cifar10.ipynb
|-- DataHandling/
|   `-- mnist_handling/
|       `-- mnist_handling.ipynb
|-- GenerativeModel/
|   |-- __init__.py
|   |-- __pycache__/
|   |   `-- __init__.cpython-39.pyc
|   |-- dataset_class/
|   |   |-- __pycache__/
|   |   |   `-- duke_dataset.cpython-39.pyc
|   |   |-- duke_dataset.py
|   |   `-- rsna_breast_cancer.py
|   |-- ddpm/
|   |   |-- import_test.py
|   |   |-- lucidrains/
|   |   |   |-- attend.py
|   |   |   |-- ddpm_lucidrains.py
|   |   |   |-- fid_evaluation.py
|   |   |   |-- train.py
|   |   |   `-- version.py
|   |   |-- origin_ddpm/
|   |   |   |-- ddpm.py
|   |   |   |-- ddpm_for_breast.py
|   |   |   |-- ddpm_for_flower102.py
|   |   |   `-- sampling_test.py
|   |   `-- simple_diffusion/
|   |       |-- __init__.py
|   |       |-- simple_diffusion.ipynb
|   |       `-- simple_diffusion.py
|   `-- normalize_test.py
|-- README.md
|-- Segmentation/
|   `-- Unet/
|       |-- data_read.py
|       `-- unet.py
|-- __init__.py
`-- __pycache__/
    `-- __init__.cpython-39.pyc

 

import_test.py

from Model_Implementation.GenerativeModel.dataset_class.duke_dataset import DukeDataset

dataset = DukeDataset()

import_test.py에서 코드를 실행하면 Model_Implementation 모듈이 존재하지 않다는 에러가 발생한다.

ModuleNotFoundError: No module named 'Model_Implementation'

 

PYTHONPATH를 사용하지 않았을 때 sys.path 출력 결과

root@39b243c21098:/workspace# /usr/bin/python /workspace/Model_Implementation/GenerativeModel/ddpm/import_test.py

['/workspace/Model_Implementation/GenerativeModel/ddpm', '/opt/conda/lib/python39.zip', 
'/opt/conda/lib/python3.9', '/opt/conda/lib/python3.9/lib-dynload', 
'/opt/conda/lib/python3.9/site-packages']

파이썬은 실행되는 파일의 위치를 sys.path에 추가하는데, 이 경우에서는 import_test.py가 실행되는 위치는 ddpm/ 디렉토리에 있기에 sys.path에는 '/workspace/Model_Implementation/GenerativeModel/ddpm' 가 추가되어있는 것을 확인할 수 있다. 그러나, 보다시피 /workspace/Model_Implementation/ 디렉토리는 sys.path에 존재하지 않으므로 모듈을 찾을 수 없는 상황이 발생하는 것이다.

 

sys.path의 첫 번째 값은 최초 실행시킨 스크립트가 위치한 디렉터리이다.

 

 


 

해결 방법

터미널에서 .py 파일 실행을 하는 경우

코드를 터미널에서 실행하는 경우는 vscode의 settings.json 파일에 해당 라인을 추가하면 된다. 

settings.json은 ctrl + shift + p를 통해 진입할 수 있다.

 

settings.json파일에는 다음과 같이 내용을 작성한다. 

{
    "terminal.integrated.env.linux": {"PYTHONPATH": "${workspaceFolder}"}
}

 

이제 다시 sys.path를 print해보면 다음과 같다.

[
'/workspace/Model_Implementation/GenerativeModel/ddpm', 
'/workspace', '/opt/conda/lib/python39.zip',
'/opt/conda/lib/python3.9', 
'/opt/conda/lib/python3.9/lib-dynload',
'/opt/conda/lib/python3.9/site-packages'
]

/workspace가 경로에 추가된 것을 확인할 수 있다. 즉, VScode에서 $workspacefolder는 내가 디렉토리의 시작지점을 /workspace로 지정했던 것을 자동으로 찾아 PYTHONPATH에 추가하여 /workspace가 sys.path에 추가된 모습이다.

 

만약, 위처럼 settings.json을 입력했는데 잘 안된다면

이처럼 VScode로 관뢰되는 프로젝트의 폴더를 workspace로 따로 저장해서 들어가는지 확인을 할 필요가 있다. 만약 이와 같이 관리되는 프로젝트라면, 아래와 같은 절차를 따른다.

  1. 위 이미지처럼 'ctrl + ,' 를 입력하여 settings에 들어온다음 `terminal.integrated.env`를 검색해서 살펴보자.
  2. 그러면 각자 운영체제에 맞는 세팅을 Edit in settings.json을 눌러 할 수 있을 것이다.

 

따로 저장하여 관리되는 workspace의 json형태이다. 따로 worksapce를 저장하여 사용할 시, settings.json과 launch.json을 한 파일에서 관리하는 형태의 JSON이 나오게된다. 이 형태에 익숙하지 않다면, `ctrl + ,` 를 눌러서 Edit in settings.json을 누르는 것이 마음 편하다.

{
	"folders": [
		{
			"path": "../프로젝트 이름",
		}
	],
	"settings": {
		"terminal.integrated.profiles.windows": {
			"PowerShell": {
				"source": "PowerShell",
				"icon": "terminal-powershell",
			},
			"Command Prompt": {
				"path": [
					"${env:windir}\\Sysnative\\cmd.exe",
					"${env:windir}\\System32\\cmd.exe"
				],
				"args": [],
				"icon": "terminal-cmd"
			},
			"Git Bash": {
				"source": "Git Bash"
			},
		},
		"terminal.integrated.env.windows": {
			"PYTHONPATH": "${workspaceFolder}"
		}
	},
	"launch": {
		"version": "0.2.0",
		"configurations": [
			{
				"name": "Python: Current File",
				"type": "python",
				"request": "launch",
				"program": "${file}",
				"console": "integratedTerminal",
				"justMyCode": true,
				"cwd": "${fileDirname}",
				"env": {"PYTHONPATH": "${workspaceFolder}${pathSeparator}${env:PYTHONPATH}"}
			}
		]
	}
}

 

 

디버깅으로 .py 파일을 실행하는 경우

해당 경우에는 settings.json 파일의 내용을 공유하지 않기에 디버깅에서도 모듈의 위치를 올바르기 인식하려면 launch.json에 내용을 작성해야 한다.

1. 실행 버튼의 사이드바를 통해 디버그로 접근
2. 왼쪽 Run&Debug탭을 통해 디버그로 접근

 

위 이미지의 어떤 방법을 사용하던 디버깅으로 접근된다. 2번 이미지의 debug 탭은 launch.json을 생성하지 않았다면, 해당 이미지처럼 생기지 않았을 수 있다.

 

 

launch.json

{
    // Use IntelliSense to learn about possible attributes.
    // Hover to view descriptions of existing attributes.
    // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
    "version": "0.2.0",
    "configurations": [
        {
            "name": "Python: Current File",
            "type": "python",
            "request": "launch",
            "program": "${file}",
            "console": "integratedTerminal",
            "justMyCode": true,
            "cwd": "${fileDirname}",
            "env": {"PYTHONPATH": "${workspaceFolder}${pathSeparator}${env:PYTHONPATH}"}
        }
    ]
}

 

 

 

참고자료

https://stackoverflow.com/questions/53653083/how-to-correctly-set-pythonpath-for-visual-studio-code

https://velog.io/@tiger/Python-%EB%AA%A8%EB%93%88%EA%B3%BC-%ED%8C%A8%ED%82%A4%EC%A7%80-%EC%B0%BE%EB%8A%94-%EB%B0%A9%EB%B2%95