2014-07-16 13 views
5

chciałbym nazwać „przerobić” narzędzia z ImageMagick z mojego skryptu Pythona przy użyciu POPEN, tak:Popen sprzecznych wykonywalnego/ścieżka

Popen(["convert", input_path, "-flop", output_file_path]) 

(Powyższy przykład po prostu odwraca obraz w poziomie)

Problem polega na tym, że po uruchomieniu skryptu w systemie Windows błędnie wywołuje narzędzie convert.exe dostarczane z systemem Windows w celu konwersji partycji FAT na system plików NTFS! (znajduje się w \ Windows \ system32)

Teraz, jeśli losowo otworzyć wiersz polecenia w dowolnym katalogu innym niż system32, i wpisz "convert", to poprawnie uruchamia plik wykonywalny ImageMagick. Oznacza to, że Popen automatycznie szuka w systemie32. Jak mogę sprawić, by nie wyglądało to w systemie32 i uruchomić poprawny plik wykonywalny?

+0

Czy próbowałeś usunąć ścieżkę do system32 z 'sys.path'? –

+1

i) system32 nie znajduje się w 'sys.path' ii)' Popen' nie wygląda w 'sys.path'. – Daniel

+0

'Popen' zaczyna się od bieżącego katalogu. Jaka jest twoja zmienna środowiskowa 'PATH'? – Daniel

Odpowiedz

7

Wyszukaj program nie jest trywialny. I'd jawnie zamiast tego podać pełną ścieżkę do pliku wykonywalnego convert.exe.

subprocess wykorzystuje CreateProcess on Windows that looks in system32 directory even before any other directory in %PATH%:

... Jeśli nazwa pliku nie zawiera rozszerzenia, .exe jest dołączany. Dlatego jeśli rozszerzeniem nazwy pliku jest .com, ten parametr musi dołączyć rozszerzenie .com. Jeśli nazwa pliku kończy się kropką (.) Z rozszerzeniem lub nazwa pliku zawiera ścieżkę, plik .exe nie jest dołączony do . Jeśli nazwa pliku nie zawiera ścieżkę do katalogu, System szuka pliku wykonywalnego w następującej kolejności:

  1. katalogu, z którego aplikacja załadowany.
  2. Bieżący katalog procesu macierzystego.
  3. 32-bitowy katalog systemu Windows. Użyj funkcji GetSystemDirectory, aby uzyskać ścieżkę do tego katalogu.
  4. 16-bitowy katalog systemu Windows. Nie ma żadnej funkcji, która uzyskałaby ścieżkę do tego katalogu, ale jest przeszukiwana. Nazwa tego katalogu to System.
  5. Katalog systemu Windows. Użyj funkcji GetWindowsDirectory, aby uzyskać ścieżkę do tego katalogu.
  6. Katalogi wymienione w zmiennej środowiskowej PATH. Zauważ, że ta funkcja nie wyszukuje ścieżki aplikacji określonej przez klucz rejestru Ścieżki aplikacji. Aby uwzględnić tę ścieżkę dla każdej aplikacji w sekwencji wyszukiwania, użyj funkcji ShellExecute.

Dlatego w tym przypadku convert jest odpowiednikiem convert.exe. Najpierw znajduje się w katalogu zawierającym sys.executable, np. C:\Python27. Następnie w bieżącym katalogu: od którego uruchomiłeś skrypt Python. Następnie w system32, gdzie znajduje się convert.exe (narzędzie systemu plików, a nie imagemagick).

Możesz spróbować usunąć katalog system32 z os.environ['PATH'] może (?) Pominąć sprawdzanie: Popen(cmd, env=no_system32_environ), ale jest delikatny (gorzej niż ścieżka jawna).

Jest powiązany problem na Python bug trackerze: "Subprocess picks the wrong executable on Windows."


cmd.exe (powłoka) korzysta z innego algorytmu. Zobacz How does Windows locate files input in the shell?

Jeśli ustawisz shell=True następnie sekwencję szukać convert programie:

  1. convert nie jest komenda wewnętrzna powłoka
  2. nie ma wyraźnego ścieżka, więc poszukiwanie kontynuuje
  3. przeszukać prąd katalog
  4. przeszukać każdy katalog określony przez zmienną środowiskową PATH, w podanej kolejności:

określa, które rozszerzenia plików są sprawdzane iw jakiej kolejności np. Convert.com, convert.exe, convert.bat, convert.cmd, jeśli %PATHEXT% to .com;.exe;.bat;.cmd.

+1

FYI, w systemie Vista i późniejszych zarówno funkcji 'CreateProcess' i' SearchForExecutable' w wywołaniu cmd.exe ['NeedCurrentDirectoryForExePath'] (https://msdn.microsoft.com/en-us/library/ms684269). Jeśli ustawisz zmienną środowiskową 'NoDefaultCurrentDirectoryInExePath', to uniemożliwi ona wyszukanie bieżącego katalogu. – eryksun

+1

Można również zauważyć, że po znalezieniu pliku cmd.exe najpierw próbuje 'CreateProcess' (bez względu na rozszerzenie pliku), a następnie próbuje' ShellExecuteEx', który pozwala na wykonywanie dowolnych typów plików. Polecenie cmd 'start' jest podobne, ale wywołuje' ShellExecuteEx' nawet jeśli nie znaleziono pliku, na przykład dla zarejestrowanych poleceń 'Ścieżki aplikacji' (np.' start/b/w python.exe' powinno działać, nawet jeśli python.exe nie jest znaleziono, ponieważ instalator powinien był zarejestrować domyślne polecenie dla "python.exe"). – eryksun

2

Jako zupełnie inne podejście, możesz wypróbować PythonMagick, opakowanie Pythona dla ImageMagick. W ten sposób możesz uzyskać dostęp do funkcji convert z poziomu Pythona i nie będziesz musiał odradzać procesów zewnętrznych.

0

Po prostu wpadłem na to sam. Uruchomienie skryptu php w powłoce ma dostęp do powłoki $ PATH, podczas gdy działanie w Apache nie (przynajmniej nie $ PATH z biblioteką Cygwin dll/exe).

Po drugie, użyj natywnej notacji Windows C:/dir/subdir/pgm w php, gdy na platformie Windows, a dostaniesz to, czego oczekujesz.

W związku z tym kod wieloplatformowy musi przełączać/opisywać ścieżkę, a następnie odwoływać się do decyzji.

Powiązane problemy