Пополняется конфликтующим исполняемым файлом / путем

Я хотел бы вызвать утилиту "конвертировать" из 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 не добавляется. Если имя файла не содержит путь к каталогу, система выполняет поиск исполняемого файла в следующей последовательности:

  1. Каталог, из которого загружено приложение.
  2. Текущий каталог для родительского процесса.
  3. 32-разрядный системный каталог Windows. Используйте функцию GetSystemDirectory, чтобы получить путь к этому каталогу.
  4. 16-разрядный системный каталог Windows. Нет функции, которая получает путь к этому каталогу, но она ищется. Название этого каталога - System.
  5. Каталог Windows. Используйте функцию GetWindowsDirectory, чтобы получить путь к этому каталогу.
  6. Каталоги, перечисленные в переменной среды 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 программа:

  1. convert не является внутренней командой оболочки
  2. явного пути нет, поэтому поиск продолжается
  3. поиск в текущем каталоге
  4. искать каждый каталог, указанный в переменной среды 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, и вы получите то, что ожидаете.

Таким образом, многоплатформенный код должен переключать / регистрировать пути, а затем ссылаться на решение.

Другие вопросы по тегам