Как мне запустить программу из Python? Сбой os.system из-за пробелов в пути

273

У меня есть сценарий Python, который должен выполнять внешнюю программу, но по какой-то причине не удается.

Если у меня есть следующий скрипт:

import os;
os.system("C:\\Temp\\a b c\\Notepad.exe");
raw_input();

Тогда это терпит неудачу со следующей ошибкой:

«C: \ Temp \ a» не распознается как внутренняя или внешняя команда, работающая программа или пакетный файл.

Если я выйду из программы с кавычками:

import os;
os.system('"C:\\Temp\\a b c\\Notepad.exe"');
raw_input();

Тогда это работает. Однако, если я добавлю параметр, он перестанет работать снова:

import os;
os.system('"C:\\Temp\\a b c\\Notepad.exe" "C:\\test.txt"');
raw_input();

Как правильно выполнить программу и дождаться ее завершения? Мне не нужно читать выходные данные из него, так как это визуальная программа, которая выполняет работу, а затем просто завершает работу, но мне нужно дождаться ее завершения.

Также обратите внимание, что перемещение программы по незаполненному пути также не вариант.


Это тоже не работает:

import os;
os.system("'C:\\Temp\\a b c\\Notepad.exe'");
raw_input();

Обратите внимание на замененные одинарные / двойные кавычки.

С или без параметра для Блокнота здесь, это не с сообщением об ошибке

Неверный синтаксис имени файла, имени каталога или метки тома.

Лассе В. Карлсен
источник
Используйте это: os.system(r'C:\temp\"a b c"\Notepad.exe') или это:os.system('C:\\temp\\"a b c"\\Notepad.exe')
chanzerre
Для будущих посетителей, если вы хотите запустить приложение с аргументами (используя подпроцесс). вам нужно разделить аргументы по пробелам и передать каждый в отдельности. Например, это из файла летучей мыши: "C:\Program Files\GDAL\gdal_translate.exe" -ot byte -of GTIFF -scale -co PHOTOMETRIC=CMYK "cmyk-16.tif" "cmyk-8_out.tif". В Python, это будет выглядеть так : ["C:\\Program Files\\GDAL\\gdal_translate.exe", "-ot", "byte", "-scale", "-co", "PHOTOMETRIC=CMYK", "input_cmyk-16.tif", "output_cmyk-8.tif"].
akinuri

Ответы:

297

subprocess.callпозволит избежать проблем, связанных с цитированием соглашений различных оболочек. Он принимает список, а не строку, поэтому аргументы легче разделить. т.е.

import subprocess
subprocess.call(['C:\\Temp\\a b c\\Notepad.exe', 'C:\\test.txt'])
Брайан
источник
81
Гораздо проще использовать необработанную строку в Windows: r "C: \ Temp \ abc \ Notepad.exe"
PierreBdR
1
Да, функции os.exec * заменят текущий процесс, поэтому процесс Python не будет продолжен. Они чаще используются в Unix, где общий метод запуска оболочки для команды - это fork (), а затем exec () в дочернем.
Брайан
1
Метод windows для этого - семейство os.spawn, которое можно использовать вместо этого. хотя подпроцесс более переносим и предлагает большую гибкость в управлении процессом (захват ввода / вывода и т. д.), поэтому он предпочтителен.
Брайан
6
@PierreBdr: есть случай, когда rawstrings не будет работать: где вам нужен косая черта. например, r'c: \ foo \ bar \ '. На самом деле, лучше использовать косую черту. Они принимаются во всем Windows API (хотя не всегда некоторыми командами оболочки (например, копировать))
Брайан
1
Для python> = 3.5 subprocess.callследует заменить на subprocess.run docs.python.org/3/library/subprocess.html#older-high-level-api
gbonetti
67

Вот другой способ сделать это.

Если вы используете Windows, следующие действия аналогичны двойному щелчку файла в проводнике или присвоению имени файла в качестве аргумента команде «start» DOS: файл открывается любым приложением (если оно есть), с которым связано его расширение. ,

filepath = 'textfile.txt'
import os
os.startfile(filepath)

Пример:

import os
os.startfile('textfile.txt')

Откроется textfile.txt с помощью Блокнота, если Блокнот связан с файлами .txt.

user16738
источник
1
Есть ли эквивалентная функция для систем * nix?
Ромено
@Romeno: вы можете попробовать: webbrowser.open("textfile.txt")он должен открыть текстовый редактор. Смотрите также «Запустите вторую программу полностью самостоятельно, как будто я просто« дважды щелкнул по ней »».
JFS
На моей установке textfile.txt должен быть в кавычках, например:os.startfile('path\to\textfile.txt')
thdoan
34

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

os.system('"C://Temp/a b c/Notepad.exe"')

'Используется Python, который затем передает "C: //Temp/abc/Notepad.exe" (как путь Windows, двойная обратная косая черта не требуется) в CMD.EXE

Даниэль Серодио
источник
1
Это кажется лучшим в сценарии, os.system('curl URL > file')где я хочу увидеть обновление индикатора прогресса cURL для действительно больших файлов.
Зак Янг
Если первая буква после обратной косой черты имеет особое значение (то есть \t, \nи т.д.) , то этот конкретный символ должен быть удвоен. Быть пути Windows не имеет к этому никакого отношения.
Итан Фурман,
1
Обратите внимание: если вы используете os.system()Windows, окно cmd будет открываться и оставаться открытым до тех пор, пока вы не закроете запущенный процесс. ИМХО лучше использовать os.startfile().
thdoan
1
Не забывайтеimport os
беши
не работает для меня stackoverflow.com/questions/56241616/…
Гульзар
19

По крайней мере, в Windows 7 и Python 3.1 os.systemв Windows требуется, чтобы командная строка заключалась в двойные кавычки, если в пути к команде есть пробелы. Например:

  TheCommand = '\"\"C:\\Temp\\a b c\\Notepad.exe\"\"'
  os.system(TheCommand)

Примером из реальной жизни, который меня озадачил, было клонирование диска в VirtualBox. Приведенное subprocess.callвыше решение не сработало из-за некоторых проблем с правами доступа, но когда я дважды цитировал команду, он os.systemобрадовался:

  TheCommand = '\"\"C:\\Program Files\\Sun\\VirtualBox\\VBoxManage.exe\" ' \
                 + ' clonehd \"' + OrigFile + '\" \"' + NewFile + '\"\"'
  os.system(TheCommand)
Пол Хоффман
источник
Вот и все! Я бы пошел subprocess, но иногда os.systemи os.popen(...).read()просто быстрее набрать. Кстати, вам не нужно , чтобы избежать двойных кавычек внутри одного, то '""C:\\Temp\\a b c\\Notepad.exe""'будет делать.
Томаш Гандор
9
import win32api # if active state python is installed or install pywin32 package seperately

try: win32api.WinExec('NOTEPAD.exe') # Works seamlessly
except: pass
Рахул
источник
и, похоже, с этим методом цитирование не требуется, например, win32api.WinExec ('pythonw.exe d: \ web2py \ web2py.py -K welcome') запускает планировщик web2py в фоновом режиме.
Тим Ричардсон
@rahul и это кроме аргументов для исполняемого файла? Итак, если вы хотите, чтобы Блокнот открыл файл или это отдельный файл?
скажем
3

Я подозреваю, что это та же проблема, что и при использовании ярлыков в Windows ... Попробуйте это:

import os;
os.system("\"C:\\Temp\\a b c\\Notepad.exe\" C:\\test.txt");
Мэтью Шарли
источник
извините, это тоже не работает, отредактированный вопрос для отражения этого.
Лассе В. Карлсен
Я думаю, что для цитирования Windows использует только «, а не». Это, вероятно, сработает, если вы измените это. Однако вы все равно столкнетесь с проблемами, если у вас есть встроенные кавычки и т. Д.
Брайан
Я думал, что потребовалось и то и другое, но вы, вероятно, правы. Я знаю, что это работает (в оболочке по крайней мере) с двойными кавычками.
Мэтью Шарли
+1 это лучший, Windows XP, 2007 Home Edition работал хорошо
0

Предположим, что мы хотим запустить ваш веб-сервер Django (в Linux), чтобы между вашим путем (path = '/home/<you>/<first-path-section> <second-path-section>') было свободное пространство , поэтому сделайте следующее:

import subprocess

args = ['{}/manage.py'.format('/home/<you>/<first-path-section> <second-path-section>'), 'runserver']
res = subprocess.Popen(args, stdout=subprocess.PIPE)
output, error_ = res.communicate()

if not error_:
    print(output)
else:
    print(error_)

[ Примечание ]:

  • Не забудьте получить разрешение на доступ: chmod 755 -R <'yor path'>
  • manage.py является исключительным: chmod +x manage.py
Беньямин Джафари
источник
0

Для Python 3.7 используйте subprocess.call . Используйте необработанную строку для упрощения путей Windows:

import subprocess
subprocess.call([r'C:\Temp\Example\Notepad.exe', 'C:\test.txt'])
WestAce
источник
0

Нет необходимости в подпроцессе, он может быть просто достигнут

GitPath = "C: \ Program Files \ Git \ git-bash.exe" # Путь к файлу приложения в mycase, его файл GITBASH os.startfile (GitPath)

раджат пракаш
источник