programing

파이썬 하위 프로세스 Popen 환경 경로?

javaba 2021. 1. 15. 19:08
반응형

파이썬 하위 프로세스 Popen 환경 경로?


subprocess사용할 때 실행 파일을 검색 하는 방법에 대해 혼란 스럽습니다 Popen(). 자식 프로세스에 대한 절대 경로가 주어지면 작동하지만 상대 경로를 사용하려고합니다. 환경 변수 PYTHONPATH를 설정하면 해당 경로에서 가져온 모듈을 가져올 수 있고 PYTHONPATH가에 있지만 .NET sys.path의 동작에 도움이되지 않는 것으로 나타났습니다 subprocess.Popen. 나는 또한 편집을 시도했습니다 sitecustomize.py에 PYTHONPATH를 추가 파일 os.environ과 같이,

# copy PYTHONPATH environment variable into PATH to allow our stuff to use
# relative paths for subprocess spawning
import os
if os.getenv('PYTHONPATH') is not None and os.getenv('PATH') is not none:
    os.environ['PATH'] = ':'.join([os.getenv('PATH'), os.getenv('PYTHONPATH')])

ipython을 사용하여 대화식으로 또는 명령 줄에서 스크립트를 실행하여 python을 시작할 때 해당 PYTHONPATH가 os.environ. 그러나 subrocess.Popen 여전히 실행 파일을 검색하지 않습니다. envkwarg가 지정 되지 않으면 부모 환경을 상속해야한다고 생각 했습니까? 다음 env으로, 먼저 복사본을 os.getenv만들고 두 번째로를 제공하여 명시 적으로 제공하려고했지만 env={'PATH': '/explicit/path/to/search/from'}여전히 실행 파일을 찾지 못했습니다. 이제 난 당황해.

예제가 내 문제를 더 명확하게 설명하는 데 도움이되기를 바랍니다.

/ dir / subdir1 /
some_executable /dir/subdir2/some_script.py

# some_script.py
from subprocess import Popen, PIPE
spam, eggs = Popen(['../subdir1/some_executable'], stdout=PIPE, stderr=PIPE).communicate()

나는에있어 경우에 /dir/subdir2나는 실행 python some_script.py작동,하지만 난에있어 경우에 /dir나는 실행 python subdir2/some_script.py하지만 심지어 /dir/subdir2os.environ['PATH'], 다음 하위 프로세스가 발생합니다 OSError: [Errno 2] No such file or directory.


(별도 답변을 위해 코멘트에서 세부 사항을 작성)

먼저, 상대 경로 (슬래시가 포함 된 경로)는 수행하는 작업에 관계없이 PATH에서 확인되지 않습니다. 현재 작업 디렉토리 에만 상대적 입니다. 상대 경로를 확인해야하는 경우 PATH를 수동으로 검색하거나 PATH를 뭉쳐서 하위 디렉터리를 포함시킨 다음 아래 제안대로 명령 이름을 사용해야합니다.

Python 스크립트의 위치에 상대적인 프로그램을 실행 하려면을 사용 __file__하고 거기에서 프로그램의 절대 경로를 찾은 다음 Popen.

둘째, Python 버그 추적기 에 Python이 베어 명령 (슬래시 없음)을 처리하는 방법에 대한 문제가 있습니다. 기본적으로 Unix / Mac에서는를 Popen사용하여 os.execvp호출 할 때 사용합니다. shell=False즉, PATH Python이 시작되었을 때 의 값을보고 아무리 변경해 os.environ도 문제를 해결하는 데 도움이 되지 않습니다 . 또한를 사용하는 Windows에서는 shell=FalsePATH에 전혀주의를 기울이지 않으며 현재 작업 디렉토리를 기준으로 만 찾습니다.

경로 평가가 필요하고 셸을 통해 명령 줄을 실행하고 싶지 않고 UNIX에있는 경우 env에서 shell=True와 같이 대신을 사용하는 것이 좋습니다 Popen(['/usr/bin/env', 'progtorun', other, args], ...). 이렇게하면 다른 PATH를 env프로세스에 전달 하여 프로그램을 찾는 데 사용할 수 있습니다. 또한 셸을 통해 인수를 전달할 때 셸 메타 문자 문제 및 잠재적 인 보안 문제를 방지합니다. 분명히 Windows (가없는 유일한 플랫폼 /usr/bin/env)에서는 다른 작업을 수행해야합니다.


PATH의 특성에 대해 약간 혼란스러워하는 것 같습니다 PYTHONPATH.

PATH 실행 파일을 검색 할 위치를 OS 셸에 알려주는 환경 변수입니다.

PYTHONPATH가져올 모듈을 검색 할 위치를 Python 인터프리터에 알려주는 환경 변수입니다. subprocess실행 파일 찾는 것과는 관련이 없습니다 .

기본 구현의 차이로 인해 subprocess.Popen는 기본적으로 비 Windows 시스템에서만 경로를 검색합니다 (Windows에는 항상 검색하는 일부 시스템 디렉터리가 있지만 PATH처리 와는 다릅니다 ). 경로를 스캔하는 유일한 신뢰할 수있는 크로스 플랫폼 방법 shell=True은 하위 프로세스 호출 에 전달 하는 것이지만 자체 문제가 있습니다 ( Popen문서에 자세히 설명되어 있음 ).

그러나 주된 문제는 Popen단순한 파일 이름이 아닌 경로 조각을 전달하는 것입니다. 디렉토리 구분 기호가 있으면 PATHWindows가 아닌 플랫폼에서도 검색 을 비활성화 할 수 있습니다 (예 : exec 기능 군에 대한 Linux 문서 참조 ).


subprocess.Popen의 상대 경로는 시스템 PATH의 요소가 아닌 현재 작업 디렉토리를 기준으로 작동합니다. 당신이 실행하는 경우 python subdir2/some_script.py에서 /dir보다 예상 실행 위치가 될 것입니다 /dir/../subdir2/some_executable일명, /subdir2/some_executable.

스크립트 자체 디렉토리에서 특정 실행 파일로의 상대 경로를 확실히 사용하려면 가장 좋은 방법은 먼저 __file__전역 변수 의 디렉토리 부분에서 절대 경로를 구성하는 것 입니다.

#/usr/bin/env python
from subprocess import Popen, PIPE
from os.path import abspath, dirname, join
path = abspath(join(dirname(__file__), '../subdir1/some_executable'))
spam, eggs = Popen(path, stdout=PIPE, stderr=PIPE).communicate()

pythonpath는 파이썬 인터프리터가 실행되는 경로로 설정됩니다. 따라서 두 번째 예의 경우 경로가 / dir / subdir2가 아닌 / dir로 설정되어 있으므로 오류가 발생합니다.

참조 URL : https://stackoverflow.com/questions/5658622/python-subprocess-popen-environment-path

반응형