Bagaimana cara menjalankan program dari Python? os.sistem gagal karena spasi di jalur

273

Saya memiliki skrip Python yang perlu menjalankan program eksternal, tetapi karena beberapa alasan gagal.

Jika saya memiliki skrip berikut:

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

Kemudian gagal dengan kesalahan berikut:

'C: \ Temp \ a' tidak dikenali sebagai perintah internal atau eksternal, program yang dapat dijalankan, atau file batch.

Jika saya keluar dari program dengan kutipan:

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

Lalu berhasil. Namun, jika saya menambahkan parameter, itu berhenti berfungsi lagi:

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

Apa cara yang tepat untuk menjalankan program dan menunggu sampai selesai? Saya tidak perlu membaca output dari itu, karena ini adalah program visual yang melakukan pekerjaan dan kemudian hanya keluar, tetapi saya harus menunggu sampai selesai.

Perhatikan juga, memindahkan program ke jalur non-spasi juga bukan pilihan.


Ini juga tidak bekerja:

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

Perhatikan tanda kutip tunggal / ganda bertukar.

Dengan atau tanpa parameter ke Notepad di sini, gagal dengan pesan kesalahan

Nama file, nama direktori, atau sintaks label volume tidak benar.

Lasse V. Karlsen
sumber
Gunakan ini: os.system(r'C:\temp\"a b c"\Notepad.exe') atau ini:os.system('C:\\temp\\"a b c"\\Notepad.exe')
chanzerre
Untuk pengunjung masa depan, jika Anda ingin menjalankan aplikasi dengan argumen (menggunakan subproses). Anda perlu membagi argumen Anda dengan spasi dan melewati masing-masing secara individual. Sebagai contoh, ini adalah dari file bat: "C:\Program Files\GDAL\gdal_translate.exe" -ot byte -of GTIFF -scale -co PHOTOMETRIC=CMYK "cmyk-16.tif" "cmyk-8_out.tif". Dalam Python, menjadi: ["C:\\Program Files\\GDAL\\gdal_translate.exe", "-ot", "byte", "-scale", "-co", "PHOTOMETRIC=CMYK", "input_cmyk-16.tif", "output_cmyk-8.tif"].
akinuri

Jawaban:

297

subprocess.callakan menghindari masalah dengan harus berurusan dengan mengutip konvensi dari berbagai kerang. Ia menerima daftar, bukan string, sehingga argumen lebih mudah dibatasi. yaitu

import subprocess
subprocess.call(['C:\\Temp\\a b c\\Notepad.exe', 'C:\\test.txt'])
Brian
sumber
81
Jauh lebih sederhana untuk menggunakan string mentah di windows: r "C: \ Temp \ abc \ Notepad.exe"
PierreBdR
1
Ya, fungsi os.exec * akan menggantikan proses saat ini, sehingga proses python Anda tidak akan dilanjutkan. Mereka lebih banyak digunakan pada unix di mana metode umum untuk shell untuk meluncurkan perintah adalah untuk fork () dan kemudian exec () pada anak.
Brian
1
Metode windows untuk ini adalah keluarga os.spawn, yang dapat digunakan sebagai gantinya. subproses lebih portabel, dan menawarkan lebih banyak fleksibilitas dalam mengendalikan proses (menangkap input / output dll), jadi lebih disukai.
Brian
6
@PierreBdr: Ada kasus di mana rawstrings tidak berfungsi: di mana Anda memerlukan garis miring. misalnya r'c: \ foo \ bar \ '. Sebenarnya, mungkin lebih baik menggunakan garis miring ke depan. Ini diterima di seluruh API windows (meskipun tidak selalu dengan beberapa perintah shell (mis. Salin))
Brian
1
Untuk python> = 3.5 subprocess.callharus diganti oleh subprocess.run docs.python.org/3/library/subprocess.html#older-high-level-api
gbonetti
67

Inilah cara berbeda untuk melakukannya.

Jika Anda menggunakan Windows, tindakan berikut seperti mengeklik dua kali file di Explorer, atau memberikan nama file sebagai argumen untuk perintah "mulai" DOS: file dibuka dengan aplikasi apa pun (jika ada) ekstensi yang terkait dengan .

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

Contoh:

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

Ini akan membuka textfile.txt dengan Notepad jika Notepad dikaitkan dengan file .txt.

pengguna16738
sumber
1
Apakah ada fungsi yang setara untuk sistem * nix?
Romeno
@Romeno: Anda dapat mencoba: webbrowser.open("textfile.txt")itu harus membuka editor teks. Lihat juga "memulai program kedua sepenuhnya sendiri, seolah-olah saya hanya 'mengklik dua kali'."
jfs
Pada setup saya textfile.txt harus dalam tanda kutip, misalnya:os.startfile('path\to\textfile.txt')
thdoan
34

Kutipan terluar dikonsumsi oleh Python sendiri, dan shell Windows tidak melihatnya. Seperti disebutkan di atas, Windows hanya memahami tanda kutip ganda. Python akan mengonversi garis depan-garis miring ke garis miring terbalik pada Windows, sehingga Anda dapat menggunakannya

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

The 'dikonsumsi oleh Python, yang kemudian meneruskan "C: //Temp/abc/Notepad.exe" (sebagai jalur Windows, tidak diperlukan backslash ganda) ke CMD.EXE

Daniel Serodio
sumber
1
Ini sepertinya yang terbaik dalam skenario seperti di os.system('curl URL > file')mana saya ingin melihat refresh meteran kemajuan CURL untuk file yang sangat besar.
Zach Young
Jika huruf pertama setelah garis miring terbalik memiliki makna khusus (yaitu \t, \n, dll) maka backslash tertentu harus dua kali lipat. Menjadi jalur Windows tidak ada hubungannya dengan itu.
Ethan Furman
1
Perhatikan bahwa jika Anda menggunakan os.system()Windows, jendela cmd akan terbuka dan tetap terbuka sampai Anda menutup proses yang dimulai. IMHO lebih baik digunakan os.startfile().
thdoan
1
Jangan lupaimport os
Besi
tidak bekerja untuk saya stackoverflow.com/questions/56241616/…
Gulzar
19

Setidaknya di Windows 7 dan Python 3.1, os.systemdi Windows ingin baris perintah dikutip ganda jika ada spasi di jalur ke perintah. Sebagai contoh:

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

Contoh dunia nyata yang membuat saya bingung adalah kloning drive di VirtualBox. The subprocess.callsolusi di atas tidak bekerja karena beberapa akses rights issue, tetapi ketika saya dikutip ganda perintah, os.systemmenjadi bahagia:

  TheCommand = '\"\"C:\\Program Files\\Sun\\VirtualBox\\VBoxManage.exe\" ' \
                 + ' clonehd \"' + OrigFile + '\" \"' + NewFile + '\"\"'
  os.system(TheCommand)
Paul Hoffman
sumber
Itu dia! Saya ingin subprocess, tapi kadang os.system- kadang dan os.popen(...).read()hanya mengetik lebih cepat. BTW, Anda tidak perlu melarikan diri dari tanda kutip ganda di dalam tunggal, yaitu '""C:\\Temp\\a b c\\Notepad.exe""'akan dilakukan.
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
sumber
dan sepertinya tidak perlu mengutip dengan metode ini, misalnya win32api.WinExec ('pythonw.exe d: \ web2py \ web2py.py -K welcome') memulai penjadwal web2py di latar belakang.
Tim Richardson
@rahul dan apakah itu kecuali argumen untuk dieksekusi? Jadi jika Anda ingin Notepad membuka file atau terpisah?
sayth
3

Saya menduga itu masalah yang sama seperti ketika Anda menggunakan pintasan di Windows ... Coba ini:

import os;
os.system("\"C:\\Temp\\a b c\\Notepad.exe\" C:\\test.txt");
Matthew Scharley
sumber
maaf, itu juga tidak berhasil, pertanyaan yang diedit untuk mencerminkan hal ini.
Lasse V. Karlsen
Saya pikir windows hanya menggunakan ", bukan 'untuk mengutip. Ini mungkin akan bekerja jika Anda mengubah ini. Namun Anda masih akan mengalami masalah dengan jika Anda telah menyertakan tanda kutip, dll.
Brian
Saya pikir butuh keduanya, tetapi Anda mungkin benar. Saya tahu itu bekerja (minimal shell) dengan tanda kutip ganda.
Matthew Scharley
+1 ini yang terbaik, windows XP, edisi rumah 2007 bekerja dengan baik
0

Misalkan kita ingin menjalankan server web Django Anda (di Linux) bahwa ada ruang di antara jalur Anda (path = '/home/<you>/<first-path-section> <second-path-section>'), jadi lakukan hal berikut:

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

[ Catatan ]:

  • Jangan lupa mengakses izin: chmod 755 -R <'yor path'>
  • manage.py dapat dijelaskan: chmod +x manage.py
Benyamin Jafari
sumber
0

Untuk Python 3.7, gunakan subprocess.call . Gunakan string mentah untuk menyederhanakan jalur Windows:

import subprocess
subprocess.call([r'C:\Temp\Example\Notepad.exe', 'C:\test.txt'])
WestAce
sumber
0

Tidak perlu untuk sub-proses, Ini hanya dapat dicapai dengan

GitPath = "C: \ Program Files \ Git \ git-bash.exe" # Path File Aplikasi dalam mycase GITBASH-nya os.startfile (GitPath)

rajat prakash
sumber