Пополняется конфликтующим исполняемым файлом / путем
Я хотел бы вызвать утилиту "конвертировать" из ImageMagick из моего скрипта Python, используя Popen, например:
Popen(["convert", input_path, "-flop", output_file_path])
(Приведенный выше пример просто переворачивает изображение по горизонтали)
Проблема в том, что когда я запускаю скрипт в Windows, он по ошибке вызывает convert.exe
Утилита, которая поставляется вместе с Windows для преобразования разделов FAT в NTFS! (находится в \Windows\system32)
Теперь, если я случайно открою командную строку в любом каталоге, кроме system32, и наберу "convert", он корректно запускает исполняемый файл ImageMagick. Таким образом, это означает, что Popen автоматически просматривает system32. Как я могу сделать так, чтобы он не смотрел в system32, а запустил правильный исполняемый файл?
3 ответа
Поиск программы не тривиален. Вместо этого я бы явно указал полный путь к исполняемому файлу convert.exe.
subprocess
использования CreateProcess
на Windows, которая выглядит в system32
каталог еще до любого другого каталога в %PATH%
:
... Если имя файла не содержит расширения,
.exe
добавлен Поэтому, если расширение имени файла -.com, этот параметр должен включать расширение.com. Если имя файла заканчивается точкой (.) Без расширения или если имя файла содержит путь,.exe не добавляется. Если имя файла не содержит путь к каталогу, система выполняет поиск исполняемого файла в следующей последовательности:
- Каталог, из которого загружено приложение.
- Текущий каталог для родительского процесса.
- 32-разрядный системный каталог Windows. Используйте функцию GetSystemDirectory, чтобы получить путь к этому каталогу.
- 16-разрядный системный каталог Windows. Нет функции, которая получает путь к этому каталогу, но она ищется. Название этого каталога - System.
- Каталог Windows. Используйте функцию GetWindowsDirectory, чтобы получить путь к этому каталогу.
- Каталоги, перечисленные в переменной среды PATH. Обратите внимание, что эта функция не выполняет поиск пути для приложения, указанного в разделе реестра "Путь к приложению". Чтобы включить этот путь для каждого приложения в последовательность поиска, используйте функцию ShellExecute.
Следовательно convert
эквивалентно convert.exe
в этом случае. Сначала он смотрит в каталог, который содержит sys.executable
например, C:\Python27
, Затем в текущем каталоге: откуда вы начали скрипт Python. Затем в system32
где он находит convert.exe
(утилита файловой системы, а не imagemagick).
Вы можете попробовать удалить каталог system32 из os.environ['PATH']
это может (?) подавить проверку этого: Popen(cmd, env=no_system32_environ)
но он хрупок (хуже, чем явный путь).
Существует проблема, связанная с системой отслеживания ошибок Python: "Подпроцесс выбирает неверный исполняемый файл в Windows".
cmd.exe
(оболочка) использует другой алгоритм. См. Как Windows находит файлы, введенные в оболочку?
Если вы установите shell=True
тогда последовательность поиска convert
программа:
convert
не является внутренней командой оболочки- явного пути нет, поэтому поиск продолжается
- поиск в текущем каталоге
- искать каждый каталог, указанный в переменной среды PATH, в указанном порядке
%PATHEXT%
определяет, какие расширения файлов проверяются и в каком порядке, например, convert.com, convert.exe, convert.bat, convert.cmd if %PATHEXT%
является .com;.exe;.bat;.cmd
,
Как совершенно другой подход, вы можете попробовать PythonMagick
, обертка Python для ImageMagick. Таким образом, вы можете получить доступ convert
работает внутри Python, и вам не придется порождать внешние процессы.
Просто столкнулся с этим сам. Запуск php-скрипта в оболочке имеет доступ к оболочке $PATH, а запуск в Apache - нет (по крайней мере, не $ PATH с Cygwin dll/exe).
Во-вторых, используйте нативную нотацию Windows C:/dir/subdir/pgm в php на платформе Windows, и вы получите то, что ожидаете.
Таким образом, многоплатформенный код должен переключать / регистрировать пути, а затем ссылаться на решение.