파이썬에서 실행 가능한 프로그램이 존재하는지 테스트하는 이식 가능하고 간단한 방법이 있습니까?
간단히 말해서 나는 which완벽한 명령 과 같은 것을 의미합니다 . PATH를 수동으로 검색하거나 Popen& al 을 사용하여 PATH를 실행 하고 실패하는지 확인하고 싶지 않습니다 (지금 내가하고있는 일이지만 상상해보십시오 launchmissiles)
which타사 모듈 : code.activestate.com/pypm/which는
파이썬에서 실행 가능한 프로그램이 존재하는지 테스트하는 이식 가능하고 간단한 방법이 있습니까?
간단히 말해서 나는 which완벽한 명령 과 같은 것을 의미합니다 . PATH를 수동으로 검색하거나 Popen& al 을 사용하여 PATH를 실행 하고 실패하는지 확인하고 싶지 않습니다 (지금 내가하고있는 일이지만 상상해보십시오 launchmissiles)
which타사 모듈 : code.activestate.com/pypm/which는
답변:
내가 생각할 수있는 가장 쉬운 방법 :
def which(program):
import os
def is_exe(fpath):
return os.path.isfile(fpath) and os.access(fpath, os.X_OK)
fpath, fname = os.path.split(program)
if fpath:
if is_exe(program):
return program
else:
for path in os.environ["PATH"].split(os.pathsep):
exe_file = os.path.join(path, program)
if is_exe(exe_file):
return exe_file
return None
편집 : 제공된 인수가 이미 실행 파일의 전체 경로 인 경우 (예 : "which / bin / ls")를 처리하기위한 논리를 포함하도록 코드 샘플이 업데이트되었습니다. 이것은 UNIX 'which'명령의 동작을 모방합니다.
편집 : 주석마다 os.path.exists () 대신 os.path.isfile ()을 사용하도록 업데이트되었습니다.
편집 : path.strip('"')여기에 잘못한 것처럼 보입니다. Windows 나 POSIX 모두 인용 된 PATH 항목을 권장하지 않습니다.
PATHEXT때문에 ENV var에 command같은 유효한 경우 command.com와 같이 script대script.bat
나는 이것이 고대의 질문이라는 것을 알고 있지만 사용할 수 있습니다 distutils.spawn.find_executable. 이것은 python 2.4 이후 로 문서화 되었으며 python 1.6 이후로 존재했습니다.
import distutils.spawn
distutils.spawn.find_executable("notepad.exe")
또한 Python 3.3은 다음을 제공합니다. shutil.which() .
win32의 distutils.spawn.find_executable구현은 단지를 찾는 .exe대신에 세트를 검색 할 확장명 목록을 사용하는 것보다 %PATHEXT%. 그것은 좋지는 않지만 누군가가 필요로하는 모든 경우에 효과적 일 수 있습니다.
from distutils import spawn php_path = spawn.find_executable("php")
distutils.spawnOS X 10.10에서 Python 2.7.6의 시스템 설치 (/ usr / bin / python)를 사용하면 분명히 AttributeError: 'module' object has no attribute 'spawn'동일한 버전의 Python을 사용하는 동일한 컴퓨터에서 작동하지만 확실하게 사용할 수는 없습니다. virtualenv 설치
import distutils.spawn또는 from distutils import spawn그냥보다는 구문을 따르십시오 import distutils. 그렇지 않으면 액세스 할 수 없으며 위와 AttributeError같은 경우에도 위의 정보를 얻을 수 있습니다.
파이썬 3.3은 이제 shutil.which ()를 제공합니다 .
my_command = 'ls'
any(os.access(os.path.join(path, my_command), os.X_OK) for path in os.environ["PATH"].split(os.pathsep))
이것은 Jay 's Answer의 한 줄짜리이며 람다 함수로도 사용됩니다.
cmd_exists = lambda x: any(os.access(os.path.join(path, x), os.X_OK) for path in os.environ["PATH"].split(os.pathsep))
cmd_exists('ls')
또는 마지막으로 함수로 들여 쓰기 :
def cmd_exists(cmd):
return any(
os.access(os.path.join(path, cmd), os.X_OK)
for path in os.environ["PATH"].split(os.pathsep)
)
import shutil
command = 'ls'
shutil.which(command) is not None
의 1 라이너로 월 - 필립 Gehrcke 응답 :
cmd_exists = lambda x: shutil.which(x) is not None
데프로서 :
def cmd_exists(cmd):
return shutil.which(cmd) is not None
x위치 에 변수를 사용 합니다.cmd
os.path.join(path, cmd)파일 인지 확인하기 위해 테스트를 추가해야합니다 . 결국, 디렉토리는 또한 실행 가능한 비트를 설정할 수 있습니다.
mkdir -p -- "$HOME"/bin/dummy && PATH="$PATH":"$HOME"/bin && python -c 'import os; print any(os.access(os.path.join(path, "dummy"), os.X_OK) for path in os.environ["PATH"].split(os.pathsep))' && rmdir -- "$HOME"/bin/dummy
and os.path.isfile(...)적절한 장소에 간단한 것을 추가하는 것으로 충분합니다
Windows에서 파일 확장자를 지정하십시오. 그렇지 않으면 환경 변수를 is_exe사용하여 창에 훨씬 복잡한 것을 작성해야 PATHEXT합니다. FindPath 만 사용하고 싶을 수도 있습니다 .
OTOH, 왜 실행 파일 검색을 귀찮게합니까? 운영 체제는 popen호출의 일부로 사용자를 대신 하여 실행 파일을 찾지 못하면 예외를 발생시킵니다. 주어진 OS에 대해 올바른 예외를 잡기 만하면됩니다. Windows에서 찾을 수 없으면 subprocess.Popen(exe, shell=True)자동으로 실패 exe합니다.
(제이의 대답에서) PATHEXT위의 구현에 통합 which:
def which(program):
def is_exe(fpath):
return os.path.exists(fpath) and os.access(fpath, os.X_OK) and os.path.isfile(fpath)
def ext_candidates(fpath):
yield fpath
for ext in os.environ.get("PATHEXT", "").split(os.pathsep):
yield fpath + ext
fpath, fname = os.path.split(program)
if fpath:
if is_exe(program):
return program
else:
for path in os.environ["PATH"].split(os.pathsep):
exe_file = os.path.join(path, program)
for candidate in ext_candidates(exe_file):
if is_exe(candidate):
return candidate
return None
yield에서 ext_candidates, 나에게 어떻게 키워드 작품의 더 나은 이해했다
이것은 나를 위해 일하는 것 같습니다 :
Mestreion 덕분에 Linux에서 작동하도록 편집
def cmd_exists(cmd):
return subprocess.call("type " + cmd, shell=True,
stdout=subprocess.PIPE, stderr=subprocess.PIPE) == 0
여기서하는 것은 내장 명령을 사용 type하고 종료 코드를 확인하는 것입니다. 그러한 명령이 없다면type 1 (또는 0이 아닌 상태 코드)으로 종료됩니다.
stdout 및 stderr에 대한 비트 type는 종료 상태 코드에만 관심이 있기 때문에 명령 출력을 침묵시키는 것 입니다.
사용법 예 :
>>> cmd_exists("jsmin")
True
>>> cmd_exists("cssmin")
False
>>> cmd_exists("ls")
True
>>> cmd_exists("dir")
False
>>> cmd_exists("node")
True
>>> cmd_exists("steam")
False
type실행 파일이 아닌 쉘 내장 기능이므로 subprocess.call()여기서 실패합니다.
OSError: [Errno 2] No such file or directory. 아마도 Mac type에서는 실제 명령 일 것입니다
shell=True및 교체 ["type", cmd]를 위해"type " + cmd
경로 이름에 대한 유용한 기능 은 os.path 모듈을 참조하십시오 . 기존 파일이 실행 가능한지 확인하려면 os.X_OK 모드와 함께 os.access (path, mode) 를 사용하십시오.
os.X_OK
path를 실행할 수 있는지 판별하기 위해 access ()의 mode 매개 변수에 포함 할 값입니다.
편집 : 제안 된 which()구현에는 os.path.join()전체 파일 이름을 작성 하는 데 사용 되는 단서가 하나 없습니다 .
허가보다 용서를 구하는 것이 더 쉽다 는 기준으로 사용하려고 시도하고 오류를 잡으려고합니다 (이 경우 OSError-파일을 확인하지 않았으며 파일을 실행할 수 없으며 둘 다 OSError를 나타냅니다).
실행 파일 --version에 빠른 no-op 플래그 와 같은 것이 있으면 도움이됩니다 .
import subprocess
myexec = "python2.8"
try:
subprocess.call([myexec, '--version']
except OSError:
print "%s not found on path" % myexec
이것은 일반적인 해결책은 아니지만 코드가 잘 알려진 단일 실행 파일을 찾아야하는 많은 사용 사례에 가장 쉬운 방법입니다.
--version라는 프로그램 을 호출 하는 것 조차 위험합니다 launchmissiles.
launchmissies미사일을 발사하지 않는 한 왜 존재 하는지 알고 싶습니까? 그것을 실행하고 종료 상태 / 예외에 따라 행동하는 것이
git맹목적으로 실행하고 싶지 않은 스텁 실행 파일도 있습니다 .
나는 여기에서 약간의 사악함을 알고 있지만이 질문을 우연히 발견했으며 모든 경우에 받아 들여진 해결책이 효과가 없었습니다. 어쨌든 제출하는 것이 도움이 될 것이라고 생각했습니다. 특히, "실행 가능"모드 감지 및 파일 확장자 제공 요구 사항. 또한 python3.3 shutil.which( PATHEXT)과 python2.4 + distutils.spawn.find_executable( '.exe') 만 추가 하면 일부 경우에만 작동합니다.
그래서 나는 "슈퍼"버전을 썼습니다 (허용 된 답변과 PATHEXTSuraj 의 제안 에 기초하여 ). 이 버전은 which작업을 좀 더 철저히 수행하고 일련의 "광역"폭 우선 기술을 먼저 시도하고 결국 PATH공간에서 보다 세분화 된 검색을 시도 합니다.
import os
import sys
import stat
import tempfile
def is_case_sensitive_filesystem():
tmphandle, tmppath = tempfile.mkstemp()
is_insensitive = os.path.exists(tmppath.upper())
os.close(tmphandle)
os.remove(tmppath)
return not is_insensitive
_IS_CASE_SENSITIVE_FILESYSTEM = is_case_sensitive_filesystem()
def which(program, case_sensitive=_IS_CASE_SENSITIVE_FILESYSTEM):
""" Simulates unix `which` command. Returns absolute path if program found """
def is_exe(fpath):
""" Return true if fpath is a file we have access to that is executable """
accessmode = os.F_OK | os.X_OK
if os.path.exists(fpath) and os.access(fpath, accessmode) and not os.path.isdir(fpath):
filemode = os.stat(fpath).st_mode
ret = bool(filemode & stat.S_IXUSR or filemode & stat.S_IXGRP or filemode & stat.S_IXOTH)
return ret
def list_file_exts(directory, search_filename=None, ignore_case=True):
""" Return list of (filename, extension) tuples which match the search_filename"""
if ignore_case:
search_filename = search_filename.lower()
for root, dirs, files in os.walk(path):
for f in files:
filename, extension = os.path.splitext(f)
if ignore_case:
filename = filename.lower()
if not search_filename or filename == search_filename:
yield (filename, extension)
break
fpath, fname = os.path.split(program)
# is a path: try direct program path
if fpath:
if is_exe(program):
return program
elif "win" in sys.platform:
# isnt a path: try fname in current directory on windows
if is_exe(fname):
return program
paths = [path.strip('"') for path in os.environ.get("PATH", "").split(os.pathsep)]
exe_exts = [ext for ext in os.environ.get("PATHEXT", "").split(os.pathsep)]
if not case_sensitive:
exe_exts = map(str.lower, exe_exts)
# try append program path per directory
for path in paths:
exe_file = os.path.join(path, program)
if is_exe(exe_file):
return exe_file
# try with known executable extensions per program path per directory
for path in paths:
filepath = os.path.join(path, program)
for extension in exe_exts:
exe_file = filepath+extension
if is_exe(exe_file):
return exe_file
# try search program name with "soft" extension search
if len(os.path.splitext(fname)[1]) == 0:
for path in paths:
file_exts = list_file_exts(path, fname, not case_sensitive)
for file_ext in file_exts:
filename = "".join(file_ext)
exe_file = os.path.join(path, filename)
if is_exe(exe_file):
return exe_file
return None
사용법은 다음과 같습니다.
>>> which.which("meld")
'C:\\Program Files (x86)\\Meld\\meld\\meld.exe'
허용되는 솔루션은 파일이 좋아 거기 때문에,이 경우에 나를 위해 일을하지 않았다 meld.1, meld.ico, meld.doap, 등 또한 허용 대답에서 실행 테스트가 불완전하고 제공했기 때문에 (전적으로 첫번째 때문에 아마도) 대신에 반환 된 하나의 디렉토리에 오 탐지.
가장 좋은 예는 Python 3의 python bulit-in 모듈 shutil.which ()입니다. 링크는 https://hg.python.org/cpython/file/default/Lib/shutil.py입니다.
StackOverflow에서 문제를 해결 한 것을 발견했습니다. 실행 파일에 무언가를 출력하고 종료 상태 0을 반환하는 옵션 (--help 또는 --version과 같은)이 있으면 작동합니다. 실행 파일에 대한 Python 호출에서 출력 억제를 참조 하십시오 . 실행 파일이 경로에 있으면이 응답의 코드 스 니펫 끝에있는 "결과"는 0이되고 그렇지 않으면 1이됩니다.
이것은 간단하게 보이고 파이썬 2와 3에서 모두 작동합니다.
try: subprocess.check_output('which executable',shell=True)
except: sys.exit('ERROR: executable not found')
command -v executable또는 type executable보편적으로 사용하십시오 . Mac에서 예상 결과를 반환하지 않는 경우가 있습니다.
중요한 질문은 " 실행 파일이 존재하는지 왜 테스트해야합니까?"입니다. 어쩌면 당신은하지 않습니까? ;-)
최근 PNG 파일 뷰어를 시작하려면이 기능이 필요했습니다. 사전 정의 된 일부 뷰어를 반복하고 존재하는 첫 번째 뷰어를 실행하고 싶었습니다. 다행히도 나는 왔습니다 os.startfile. 훨씬 낫다! 간단하고 휴대 가능하며 시스템 에서 기본 뷰어를 사용합니다 .
>>> os.startfile('yourfile.png')
업데이트 :os.startfile 휴대용 이 잘못되었습니다 ... Windows 만입니다. Mac에서는 open명령 을 실행해야합니다 . 그리고 xdg_open유닉스에서. 에 대한 Mac 및 Unix 지원 추가에 대한 Python 문제 가 있습니다 os.startfile.
"sh"( http://amoffat.github.io/sh/ ) 라는 외부 라이브러리를 사용해 볼 수 있습니다 .
import sh
print sh.which('ls') # prints '/bin/ls' depending on your setup
print sh.which('xxx') # prints None
추가 된 윈도우 지원
def which(program):
path_ext = [""];
ext_list = None
if sys.platform == "win32":
ext_list = [ext.lower() for ext in os.environ["PATHEXT"].split(";")]
def is_exe(fpath):
exe = os.path.isfile(fpath) and os.access(fpath, os.X_OK)
# search for executable under windows
if not exe:
if ext_list:
for ext in ext_list:
exe_path = "%s%s" % (fpath,ext)
if os.path.isfile(exe_path) and os.access(exe_path, os.X_OK):
path_ext[0] = ext
return True
return False
return exe
fpath, fname = os.path.split(program)
if fpath:
if is_exe(program):
return "%s%s" % (program, path_ext[0])
else:
for path in os.environ["PATH"].split(os.pathsep):
path = path.strip('"')
exe_file = os.path.join(path, program)
if is_exe(exe_file):
return "%s%s" % (exe_file, path_ext[0])
return None
그것은 보인다 분명 "어떤"는 popen을 통해 결과를 분석 선택이 될 것입니다하지만 당신은 그렇지 않으면 운영 체제 클래스를 사용하여 시뮬레이션 할 수 있습니다. pseudopython에서는 다음과 같습니다.
for each element r in path:
for each file f in directory p:
if f is executable:
return True
which명령 이 없습니다 . UnxUtils 버전이 있지만 확장명을 알고 / 지정해야합니다. 그렇지 않으면 프로그램을 찾을 수 없습니다.
파이썬 패브릭 라이브러리 사용하기 :
from fabric.api import *
def test_cli_exists():
"""
Make sure executable exists on the system path.
"""
with settings(warn_only=True):
which = local('which command', capture=True)
if not which:
print "command does not exist"
assert which
which(1)로 모든 시스템에 존재하지 않는 시스템에 따라 다릅니다 .