Czy w Pythonie istnieje przenośny i prosty sposób sprawdzenia, czy istnieje program wykonywalny?
Przez proste rozumiem coś w rodzaju which
polecenia, które byłoby po prostu idealne. Nie chcę ręcznie szukać ŚCIEŻKI lub czegoś, co wymaga próby wykonania jej za pomocą Popen
& al i sprawdzenia, czy się nie powiedzie (to właśnie robię teraz, ale wyobraź sobie, że to launchmissiles
)
which
moduł innej firmy: code.activestate.com/pypm/whichOdpowiedzi:
Najprostszy sposób, w jaki mogę myśleć:
Edycja : Zaktualizowano przykładowy kod, aby zawierał logikę do obsługi przypadku, w którym podany argument jest już pełną ścieżką do pliku wykonywalnego, tj. „What / bin / ls”. To naśladuje zachowanie polecenia UNIX „który”.
Edycja : Zaktualizowano, aby używać komend os.path.isfile () zamiast os.path.exists () w komentarzach.
Edycja :
path.strip('"')
wydaje się, że to niewłaściwa rzecz do zrobienia tutaj. Ani Windows, ani POSIX nie wydają się zachęcać do cytowanych pozycji ŚCIEŻKA.źródło
PATHEXT
env var ponieważcommand
jest tak ważna,command.com
jakscript
vsscript.bat
Wiem, że to starożytne pytanie, ale możesz z niego skorzystać
distutils.spawn.find_executable
. Zostało to udokumentowane od wersji Python 2.4 i istnieje od wersji Python 1.6.Ponadto oferuje teraz Python 3.3
shutil.which()
.źródło
win32
Thedistutils.spawn.find_executable
realizacja tylko wygląda na.exe
raczej niż przy użyciu listę rozszerzeń, aby szukać w zestawie%PATHEXT%
. To nie jest świetne, ale może działać we wszystkich przypadkach, których ktoś potrzebuje.from distutils import spawn
php_path = spawn.find_executable("php")
distutils.spawn
nie jest dostępny niezawodnie: z moją instalacją systemu (/ usr / bin / python) Python 2.7.6 na OS X 10.10, otrzymuję:AttributeError: 'module' object has no attribute 'spawn'
chociaż dziwnie działa na tej samej maszynie z tą samą wersją Pythona, ale z instalacja virtualenv.import distutils.spawn
, że postępujesz zgodnie zefrom distutils import spawn
składnią, a nie tylkoimport distutils
. W przeciwnym razie może nie być dostępny i otrzymasz powyższe,AttributeError
nawet jeśli tam jest.Python 3.3 oferuje teraz shutil.which () .
źródło
W przypadku python 3.2 i wcześniejszych:
To jest jednowierszowa odpowiedź Jaya , również tutaj jako funkcja lambda:
Lub wreszcie, wcięte jako funkcja:
W przypadku python 3.3 i nowszych:
Jako jedno-linijka odpowiedzi Jana-Philipa Gehrckego :
Z definicji:
źródło
x
tam, gdzie powinna byćcmd
os.path.join(path, cmd)
plik jest, prawda? W końcu katalogi mogą mieć również ustawiony bit wykonywalny ...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(...)
Wystarczy dodać prosty do odpowiednich miejsc, aby to naprawićPamiętaj tylko, aby określić rozszerzenie pliku w systemie Windows. W przeciwnym razie musisz napisać bardzo skomplikowane
is_exe
dla systemu Windows przy użyciuPATHEXT
zmiennej środowiskowej. Możesz po prostu użyć FindPath .OTOH, dlaczego w ogóle zawracasz sobie głowę szukaniem pliku wykonywalnego? System operacyjny zrobi to za Ciebie w ramach
popen
wywołania i zgłosi wyjątek, jeśli plik wykonywalny nie zostanie znaleziony. Wszystko, co musisz zrobić, to złapać poprawny wyjątek dla danego systemu operacyjnego. Pamiętaj, że w systemie Windowssubprocess.Popen(exe, shell=True)
nie powiedzie się po cichu, jeśliexe
nie zostanie znaleziony.Włączenie
PATHEXT
do powyższej implementacjiwhich
(w odpowiedzi Jaya):źródło
yield
inext_candidates
, pozwoliło mi lepiej zrozumieć, jak działa to słowo kluczoweDla platform * nix (Linux i OS X)
To wydaje się działać dla mnie:
Edytowane do pracy w systemie Linux, dzięki Mestreion
To, co tu robimy, to użycie wbudowanego polecenia
type
i sprawdzenie kodu wyjścia. Jeśli nie ma takiego polecenia,type
wyjdzie z 1 (lub niezerowym kodem statusu i tak).Trochę o stdout i stderr jest po prostu wyciszenie wyniku
type
polecenia, ponieważ interesuje nas tylko kod statusu wyjścia.Przykładowe użycie:
źródło
type
ma wbudowaną powłokę, a nie plik wykonywalny, więcsubprocess.call()
tutaj zawodzi.OSError: [Errno 2] No such file or directory
. Być może na Macutype
jest faktyczne polecenieshell=True
i wymienić["type", cmd]
na"type " + cmd
Zobacz moduł os.path , aby uzyskać przydatne funkcje w ścieżkach. Aby sprawdzić, czy istniejący plik jest wykonywalny, użyj os.access (ścieżka, tryb) w trybie os.X_OK.
EDYCJA: W sugerowanych
which()
implementacjach brakuje jednej wskazówki - używanejos.path.join()
do budowania pełnych nazw plików.źródło
Na podstawie tego, że łatwiej jest poprosić o wybaczenie niż o pozwolenie , po prostu spróbuję go użyć i złapać błąd (w tym przypadku OSError - sprawdziłem, czy plik nie istnieje i plik nie jest wykonywalny, a oba dają OSError).
Pomaga, jeśli plik wykonywalny ma coś w rodzaju
--version
flagi, która szybko uniemożliwia działanie.Nie jest to ogólne rozwiązanie, ale będzie najłatwiejszym sposobem dla wielu przypadków użycia - tych, w których kod musi szukać jednego dobrze znanego pliku wykonywalnego.
źródło
--version
programu o nazwielaunchmissiles
!launchmissies
istnieje, chyba że chcesz wystrzelić pociski? Lepiej go wykonać i działać zgodnie ze statusem wyjścia / wyjątkamigit
Że prawdopodobnie nie chcesz uruchamiać się na ślepo.Wiem, że jestem tu trochę nekromantą, ale natknąłem się na to pytanie i zaakceptowane rozwiązanie nie działało dla mnie we wszystkich przypadkach. Pomyślałem, że i tak warto je złożyć. W szczególności wykrywanie trybu „wykonywalnego” i wymóg podania rozszerzenia pliku. Ponadto, zarówno python3.3
shutil.which
(używaPATHEXT
), jak i python2.4 +distutils.spawn.find_executable
(tylko próbuje dodać'.exe'
) działają tylko w podzbiorze przypadków.Napisałem więc „super” wersję (na podstawie zaakceptowanej odpowiedzi i
PATHEXT
sugestii Suraja). Ta wersjawhich
wykonuje to zadanie nieco dokładniej i najpierw wypróbowuje szereg technik „szerokofazowych”, a ostatecznie próbuje bardziej szczegółowych wyszukiwań wPATH
przestrzeni:Sposób użycia wygląda następująco:
Przyjętego rozwiązania nie działa dla mnie w tym przypadku, ponieważ nie były plików, takich jak
meld.1
,meld.ico
,meld.doap
itp również w katalogu, z których jedno zostało zwróconych zamiast (przypuszczalnie od leksykograficznie pierwszy) bo wykonywalny testy w przyjętym odpowiedź była niepełna i daje fałszywie pozytywne.źródło
Najlepszym przykładem powinien być moduł wbudowany w python shutil.which () w Python 3. Link to https://hg.python.org/cpython/file/default/Lib/shutil.py
źródło
W StackOverflow znalazłem coś, co rozwiązało problem. Działa to pod warunkiem, że plik wykonywalny ma opcję (np. --Help lub --version), która wyświetla coś i zwraca wartość wyjścia równą zero. Zobacz Pomijanie danych wyjściowych w wywołaniach Pythona w plikach wykonywalnych - „wynik” na końcu fragmentu kodu w tej odpowiedzi wyniesie zero, jeśli plik wykonywalny znajduje się na ścieżce, w przeciwnym razie najprawdopodobniej będzie to 1.
źródło
Wydaje się to dość proste i działa zarówno w Pythonie 2, jak i 3
źródło
command -v executable
lub,type executable
aby być uniwersalnym. Są przypadki, w których na komputerach Mac nie zwraca się oczekiwanych wyników.Ważnym pytaniem jest „ Dlaczego musisz sprawdzić, czy istnieje plik wykonywalny?” Może nie? ;-)
Ostatnio potrzebowałem tej funkcji, aby uruchomić przeglądarkę plików PNG. Chciałem przeprowadzić iterację nad niektórymi predefiniowanymi przeglądarkami i uruchomić pierwszą, która istnieje. Na szczęście trafiłem
os.startfile
. Jest dużo lepiej! Prosty, przenośny i korzysta z domyślnej przeglądarki w systemie:Aktualizacja: Myliłem się co
os.startfile
do przenośności ... To tylko system Windows. Na Macu musisz uruchomićopen
polecenie. Ixdg_open
na Uniksie. Podczas dodawania obsługi komputerów Mac i Unix występuje problem w języku Pythonos.startfile
.źródło
Możesz wypróbować zewnętrzną bibliotekę lib o nazwie „sh” ( http://amoffat.github.io/sh/ ).
źródło
Dodano obsługę systemu Windows
źródło
możesz stwierdzić, czy plik istnieje z modułem OS. w szczególności plik wykonywalny wydaje się dość niesportowalny, biorąc pod uwagę, że wiele elementów jest wykonywalnych w systemie nix, których nie ma w systemie Windows i odwrotnie.
źródło
Wydaje się, że oczywistym wyborem jest „które”, analizując wyniki za pomocą popen, ale można to zasymulować w inny sposób, używając klasy os. W pseudopytonie wyglądałoby to tak:
źródło
which
polecenia; istnieje wersja UnxUtils, ale musisz znać / określić rozszerzenie, w przeciwnym razie program nie zostanie znaleziony.Zasadniczo chcesz znaleźć plik w zamontowanym systemie plików (niekoniecznie tylko w katalogach PATH) i sprawdzić, czy jest wykonywalny. Przekłada się to na następujący plan:
Powiedziałbym, że wykonanie tego w sposób przenośny będzie wymagało dużej mocy obliczeniowej i czasu. Czy to naprawdę to, czego potrzebujesz?
źródło
W standardowej dystrybucji języka Python znajduje się skrypt what.py (np. W systemie Windows
'\PythonXX\Tools\Scripts\which.py'
).EDYCJA:
which.py
zależy od tego,ls
dlatego nie jest wieloplatformowa.źródło
Żaden z poprzednich przykładów nie działa na wszystkich platformach. Zwykle nie działają one w systemie Windows, ponieważ można wykonać bez rozszerzenia pliku i zarejestrować nowe rozszerzenie. Na przykład w systemie Windows, jeśli Python jest dobrze zainstalowany, wystarczy uruchomić plik „file.py” i będzie działać.
Jedynym prawidłowym i przenośnym rozwiązaniem, jakie miałem, było wykonanie polecenia i wyświetlenie kodu błędu. Każdy przyzwoity plik wykonywalny powinien mieć zestaw parametrów wywoływania, które nic nie zrobią.
źródło
Za pomocą biblioteki tkanin Python:
źródło
which(1)
który nie jest obecny we wszystkich systemach.