Як виконати програму з 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

Для майбутніх відвідувачів, якщо ви хочете запустити додаток з аргументами (використовуючи підпроцес). вам потрібно розділити свої аргументи на пробіл і передати кожен окремо. Наприклад, це з файлу bat : "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 \ '. Насправді, напевно, краще замість цього використовувати прямі нахили. Вони приймаються у вікні API (хоча не завжди в деяких командах оболонок (наприклад, копія))
Brian

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.


1
Чи існує еквівалентна функція для * nix систем?
Ромено

@Romeno: ви можете спробувати: webbrowser.open("textfile.txt")він повинен відкрити текстовий редактор. Дивіться також "запустити другу програму повністю самостійно, наче я просто" двічі клацнув її ".
jfs

У моїй os.startfile('path\to\textfile.txt')
настройці textfile.txt

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 для дійсно великих файлів.
Zach Young

Якщо перша буква після зворотної косої межі має особливе значення (тобто \t, \nі т.д.) , то цей конкретний символ повинен бути подвоєний. Бути шлях до Windows не має нічого спільного.
Етан Фурман

1
Зауважте, що якщо ви використовуєте os.system()в Windows, вікно cmd відкриється та залишатиметься відкритим, поки ви не закриєте процес, який він почав. ІМХО краще використовувати os.startfile().
thdoan

1
Не забувайтеimport os
Бесі

не працює для мене stackoverflow.com/questions/56241616/…
Gulzar

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 ласкаво просимо') запускає web2py планувальник у фоновому режимі.
Тім Річардсон,

@rahul і чи це, крім аргументів для виконуваного файлу? Тож якщо ви хочете, щоб «Блокнот» відкрив файл або це окремо?
сказати


3

Я підозрюю, що це та сама проблема, що і при використанні ярликів у Windows ... Спробуйте це:

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

Вибачте, що не працює, відредаговане питання, щоб відобразити це.
Лассе В. Карлсен

Я думаю, що Windows використовує лише ", а не" для цитування. Це, мабуть, спрацює, якщо ви це зміните. Однак ви все ще зіткнетеся з проблемами, якщо у вас вбудовані цитати тощо.
Брайан,

Я думав, що це знадобиться обом, але ти, мабуть, маєш рацію. Я знаю, що це працює (принаймні в оболонці) з подвійними цитатами.
Меттью Шарлі

+1 це найкращий варіант, домашня редакція Windows XP, 2007 працювала чудово

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'])

0

Немає потреби в підпроцесі, цього можна просто досягти

GitPath = "C: \ Програмні файли \ Git \ git-bash.exe" # Шлях до файлу додатка в моєму коді його GITBASH os.startfile (GitPath)

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.