crontab과 python script 파일을 연동시킬 때 절대 경로 문제가 많이 발생하게 되는데요. 특히나, 스크립트 내에 google api라던지 다른 api와 연동하기 위해 파일을 읽어들일 때 이런 이슈가 발생하곤 합니다. 어떻게 발생했는지 알아보고, 어떻게 python script file의 현재 경로를 얻어오는지도 알아봅시다.

 


 

 먼저 홈 디렉토리의 test 폴더에 1.py와 emoji.txt가 있습니다.

 

 

 emoji.txt를 읽기 전용으로 열기만 하고 끝내는 프로그램입니다. 이것을 test 폴더 내에서 python3 1.py를 수행했으면 사실상 별 문제가 없었을 겁니다. 그런데, 주기적으로 실행하는 스케쥴러 같은 경우, test 폴더에서 수행하지는 않을 겁니다.

 

 

 어? 없다고 뜨네요? 왜 그럴까요? 간단하게 strace로 trace 해 보겠습니다.

 

 

 위 명령어는 python3 test/1.py의 trace 결과를 strace.out으로 떨굽니다.

 

 

 이제, emoji가 들어간 키워드만 봅시다. 그러면, "emoji.txt" 라는 게 있고 1번째 인자에 AT_FDCWD가 있습니다? 문서를 보면, 2번째 인자가 상대경로였고, 1번째 인자에 AT_FDCWD가 켜져 있었기 때문에, current_working_directory를 기준으로 작동합니다. 어떤 것의? calling process의. 한 가지 확실한 것은 openat를 부른 프로세스의 작업 디렉토리가 test 폴더 밑에 있지는 않았을 겁니다. 이건 어떻게 알 수 있을까요?

 

 

 pstree -p를 보면 python3의 pid가 나옵니다. 2043이네요. /proc/{pid}는 해당 pid를 가지는 프로세스에 대한 무언가를 저장하고 있습니다. 그리고 문서를 보면, cwd가 해당 프로세스의 working directory이므로, cwd만 보면 되겠습니다.

 

 

 보니까 /home/chokw를 working directory로 가지고 있네요. 여기에는 emoji.txt가 없으므로 파일 not found가 떨어지게 될 겁니다. 당연한 이야기겠네요.

 

 만약에 test 폴더 내에서 python3 1.py를 수행하면 어떨까요? 이 때에는 cwd가 /home/chokw/test로 잡힌 것을 볼 수 있어요. 이 폴더 안에 emoji.txt가 있으니, open("emoji.txt", "r")을 해도 파일이 없다는 예외가 잡히지 않습니다.

 

 


 현재 python interpreter가 invoke한 script가 속한 디렉토리의 절대 경로를 가져오고 싶다면, sys.path[0]을 입력하면 됩니다. 이는 문서에도 설명이 되어 있는 부분입니다.

 

 

 다시 python3 test/1.py를 입력해 보면, /home/chokw/test/emoji.txt를 열었다고 나오는데요. py_path로 /home/chokw/test가 인식되었습니다. 이는 인터프리터가 invoke한 script가 /home/chokw/test/1.py였기 때문입니다. 1.py가 있었던 디렉토리의 절대 경로는 /home/chokw/test였으니까 당연한 결과입니다.

 

 그러면 여기서 문제. 아래 프로그램의 결과는 어떨까요?

 


 프로젝트의 구조는 위와 같습니다.

 

 

 main.py입니다. sys.path[0]을 출력하고 test.go에 있는 foo를 호출합니다.

 

 

 test package 안에 있는 go.py입니다. foo 역시 sys.path[0]을 호출하고 있습니다. 결과는 어떨까요? go.py에서는, go.py가 있는 디렉토리의 절대경로를 출력할까요?

 

 

 정답은 아닙니다. 왜냐하면, 인터프리터가 invoke한 것은 main.py였기 때문입니다. 만약에, go.py의 절대 경로를 가져오려면 어떻게 해야 할까요? 이 때에는 __file__과 abspath 등을 이용하면 됩니다.

 

 

 6번째 줄은 해당 py 파일의 절대 경로를 출력하는 역할을 합니다.