Jak wykonać program z Pythona? os.system zawiedzie z powodu spacji w ścieżce

273

Mam skrypt w języku Python, który musi uruchomić program zewnętrzny, ale z jakiegoś powodu kończy się niepowodzeniem.

Jeśli mam następujący skrypt:

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

Następnie kończy się niepowodzeniem z następującym błędem:

„C: \ Temp \ a” nie jest rozpoznawane jako polecenie wewnętrzne lub zewnętrzne, program operacyjny lub plik wsadowy.

Jeśli wyjdę z programu z cytatami:

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

To działa. Jeśli jednak dodam parametr, przestanie on działać:

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

Jaki jest właściwy sposób wykonania programu i oczekiwania na jego zakończenie? Nie muszę czytać z niego danych wyjściowych, ponieważ jest to program wizualny, który wykonuje zadanie, a następnie po prostu wychodzi, ale muszę poczekać, aż się zakończy.

Zauważ też, że przeniesienie programu na ścieżkę nieprzestrzenną również nie jest opcją.


To również nie działa:

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

Uwaga zamienione pojedyncze / podwójne cudzysłowy.

Z parametrem Notatnika lub bez niego, komunikat o błędzie nie powiedzie się

Nazwa pliku, nazwa katalogu lub składnia etykiety woluminu jest niepoprawna.

Lasse V. Karlsen
źródło
Użyj tego: os.system(r'C:\temp\"a b c"\Notepad.exe') lub tego:os.system('C:\\temp\\"a b c"\\Notepad.exe')
chanzerre
Dla przyszłych gości, jeśli chcesz uruchomić aplikację z argumentami (przy użyciu podprocesu). musisz podzielić argumenty na spację i przekazać każdy z osobna. Na przykład, jest to z pliku bat: "C:\Program Files\GDAL\gdal_translate.exe" -ot byte -of GTIFF -scale -co PHOTOMETRIC=CMYK "cmyk-16.tif" "cmyk-8_out.tif". W Pythonie, staje się: ["C:\\Program Files\\GDAL\\gdal_translate.exe", "-ot", "byte", "-scale", "-co", "PHOTOMETRIC=CMYK", "input_cmyk-16.tif", "output_cmyk-8.tif"].
akinuri

Odpowiedzi:

297

subprocess.calluniknie problemów z radzeniem sobie z konwencjami cytowania różnych powłok. Przyjmuje listę, a nie ciąg znaków, więc argumenty można łatwiej oddzielić. to znaczy

import subprocess
subprocess.call(['C:\\Temp\\a b c\\Notepad.exe', 'C:\\test.txt'])
Brian
źródło
81
Znacznie prostsze jest stosowanie nieprzetworzonego ciągu w
systemie
1
Tak, funkcje os.exec * zastąpią bieżący proces, więc proces w Pythonie nie będzie kontynuowany. Są one używane częściej w Uniksie, gdzie ogólną metodą powłoki do uruchomienia polecenia jest fork (), a następnie exec () w potomku.
Brian
1
Metodą Windows jest do tego rodzina os.spawn, którą można zamiast tego użyć. podproces jest jednak bardziej przenośny i oferuje większą elastyczność w kontrolowaniu procesu (przechwytywanie danych wejściowych / wyjściowych itp.), dlatego jest preferowany.
Brian
6
@PierreBdr: Istnieje przypadek, w którym nieprzetworzone łańcuchy nie będą działać: gdzie potrzebujesz końcowego ukośnika. np. r'c: \ foo \ bar \ '. Właściwie lepiej jest zamiast tego używać ukośników. Są one akceptowane w interfejsie API systemu Windows (choć nie zawsze przez niektóre polecenia powłoki (np. Kopiowanie))
Brian,
1
W przypadku python> = 3.5 subprocess.callnależy zastąpić subprocess.run docs.python.org/3/library/subprocess.html#older-high-level-api
gbonetti
67

Oto inny sposób na zrobienie tego.

Jeśli używasz systemu Windows, poniższe czynności działają jak dwukrotne kliknięcie pliku w Eksploratorze lub podanie nazwy pliku jako argumentu polecenia „start” systemu DOS: plik jest otwierany za pomocą dowolnej aplikacji (jeśli istnieje), z którą jest powiązane rozszerzenie .

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

Przykład:

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

Spowoduje to otwarcie pliku tekstowego.txt w Notatniku, jeśli Notatnik jest powiązany z plikami .txt.

użytkownik16738
źródło
1
Czy istnieje równoważna funkcja dla systemów * nix?
Romeno
@Romeno: możesz spróbować: webbrowser.open("textfile.txt")powinien otworzyć edytor tekstu. Zobacz także: „uruchom drugi program całkowicie samodzielnie, jakbym po prostu„ dwukrotnie go kliknął ”.”
jfs
W moim ustawieniu plik textfile.txt musi znajdować się w cudzysłowie, np .:os.startfile('path\to\textfile.txt')
thdoan
34

Najbardziej zewnętrzne cytaty są pobierane przez sam Python, a powłoka systemu Windows tego nie widzi. Jak wspomniano powyżej, system Windows obsługuje tylko cudzysłowy. Python przekonwertuje ukośniki do tyłu na odwrotne ukośniki w systemie Windows, dzięki czemu możesz używać

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

Plik „jest konsumowany przez Python, który następnie przekazuje„ C: //Temp/abc/Notepad.exe ”(jako ścieżka systemu Windows, nie wymaga podwójnych ukośników odwrotnych) do CMD.EXE

Daniel Serodio
źródło
1
Wydaje się to najlepsze w scenariuszu, w os.system('curl URL > file')którym chcę zobaczyć odświeżanie miernika postępu cURL dla naprawdę dużych plików.
Zach Young,
Jeżeli pierwsza litera po backslashem ma szczególne znaczenie (tzn \t, \nitp), a następnie, że szczególną backslash musi być podwojona. Bycie ścieżką systemu Windows nie ma z tym nic wspólnego.
Ethan Furman,
1
Pamiętaj, że jeśli używasz os.system()w systemie Windows, okno cmd otworzy się i pozostanie otwarte, dopóki nie zamkniesz procesu, który rozpoczął. IMHO lepiej użyć os.startfile().
thdoan
1
Nie zapomnijimport os
Besi
nie działa dla mnie stackoverflow.com/questions/56241616/…
Gulzar
19

Przynajmniej w Windows 7 i Python 3.1, os.systemw Windows chce podwójnego cudzysłowu, jeśli w ścieżce do polecenia są spacje. Na przykład:

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

Przykładem, który mnie prześladował, było klonowanie dysku w VirtualBox. Powyższe subprocess.callrozwiązanie nie zadziałało z powodu pewnych problemów z prawami dostępu, ale kiedy podwoiłem polecenie, byłem os.systemszczęśliwy:

  TheCommand = '\"\"C:\\Program Files\\Sun\\VirtualBox\\VBoxManage.exe\" ' \
                 + ' clonehd \"' + OrigFile + '\" \"' + NewFile + '\"\"'
  os.system(TheCommand)
Paul Hoffman
źródło
To było to! Wybrałbym subprocess, ale czasami os.systemi os.popen(...).read()są po prostu szybciej pisać. BTW, nie musisz uciekać podwójnych cudzysłowów wewnątrz singla, czyli '""C:\\Temp\\a b c\\Notepad.exe""'zrobi.
Tomasz Gandor
9
import win32api # if active state python is installed or install pywin32 package seperately

try: win32api.WinExec('NOTEPAD.exe') # Works seamlessly
except: pass
Rahul
źródło
i wydaje się, że ta metoda nie wymaga cytowania, np. win32api.WinExec ('pythonw.exe d: \ web2py \ web2py.py -K welcome') uruchamia program planujący web2py w tle.
Tim Richardson,
@rahul i czy poza argumentami pliku wykonywalnego? Więc jeśli chcesz, aby Notatnik otworzył plik, czy to jest osobne?
mówi
3

Podejrzewam, że to ten sam problem, co w przypadku korzystania ze skrótów w systemie Windows ... Wypróbuj to:

import os;
os.system("\"C:\\Temp\\a b c\\Notepad.exe\" C:\\test.txt");
Matthew Scharley
źródło
przepraszam, to też nie działa, edytowane pytanie, aby to odzwierciedlić.
Lasse V. Karlsen
Myślę, że Windows używa do cytowania tylko „, a nie”. Prawdopodobnie to zadziała, jeśli to zmienisz. Jednak nadal będziesz mieć problemy z osadzonymi cytatami itp.
Brian
Myślałem, że zajęło to oba, ale prawdopodobnie masz rację. Wiem, że to działa (przynajmniej w powłoce) z podwójnymi cudzysłowami.
Matthew Scharley,
+1 to jest najlepszy, Windows XP, edycja domowa 2007 działała ładnie
0

Załóżmy, że chcemy uruchomić serwer WWW Django (w systemie Linux), aby między ścieżką (ścieżka = '/home/<you>/<first-path-section> <second-path-section>') była przestrzeń, więc wykonaj następujące czynności:

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_)

[ Uwaga ]:

  • Nie zapomnij uzyskać dostępu do uprawnień: chmod 755 -R <'yor path'>
  • manage.py jest możliwe do wykonania: chmod +x manage.py
Benyamin Jafari
źródło
0

W przypadku Python 3.7 użyj subprocess.call . Użyj surowego ciągu znaków, aby uprościć ścieżki systemu Windows:

import subprocess
subprocess.call([r'C:\Temp\Example\Notepad.exe', 'C:\test.txt'])
WestAce
źródło
0

Nie ma potrzeby podprocesu, można to po prostu osiągnąć

GitPath = "C: \ Program Files \ Git \ git-bash.exe" # Ścieżka pliku aplikacji mycase jego GITBASH os.startfile (GitPath)

rajat prakash
źródło