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();

入れ替えられた一重/二重引用符に注意してください。

ここでメモ帳へのパラメーターの有無にかかわらず、エラーメッセージで失敗します

ファイル名、ディレクトリ名、またはボリュームラベルの構文が正しくありません。


this:os.system(r'C:\temp\"a b c"\Notepad.exe') またはthis: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プロセスは続行されません。それらは、シェルがコマンドを起動する一般的な方法がfork()で、次に子でexec()を実行するUNIXでより多く使用されます。
ブライアン、

1
このためのWindowsメソッドはos.spawnファミリーであり、代わりに使用できます。ただし、サブプロセスは移植性が高く、プロセスの制御(入力/出力のキャプチャーなど)の柔軟性が高いため、推奨されます。
ブライアン、

6
@PierreBdr:rawstringsが機能しない場合があります:末尾にスラッシュが必要な場合です。例:r'c:\ foo \ bar \ '。実際には、代わりにスラッシュを使用する方が良いでしょう。これらはWindows API全体で受け入れられます(ただし、一部のシェルコマンド(たとえば、コピー)では常にではありません)
Brian

1
Python> = 3.5のsubprocess.call場合は、subprocess.run docs.python.org
/

67

これを行う別の方法を次に示します。

Windowsを使用している場合、エクスプローラーでファイルをダブルクリックする、またはDOSの "start"コマンドの引数としてファイル名を指定するなどの動作を行います。ファイルは、拡張子が関連付けられているアプリケーション(ある場合)で開かれます。 。

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

例:

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

これは、メモ帳が.txtファイルに関連付けられている場合、textfile.txtをメモ帳で開きます。


1
* nixシステムに同等の機能はありますか?
Romeno

@Romeno:試すことができます:webbrowser.open("textfile.txt")テキストエディターが開きます。参照してください。「私は単に『それをダブルクリックした』かのように、自分自身で完全に2番目のプログラムを起動します。」
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 2014

1
忘れないでくださいimport os
Besi

私にとって仕事はしません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.systemos.popen(...).read()だけ速くタイプです。ところで、一重引用符内で二重引用符をエスケープする必要はあり'""C:\\Temp\\a b c\\Notepad.exe""'ません。
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

このメソッドでは引用符は必要ないようです。たとえば、win32api.WinExec( 'pythonw.exe d:\ web2py \ web2py.py -K welcome')は、web2pyスケジューラをバックグラウンドで開始します。
ティム・リチャードソン

@rahul、それは実行可能ファイルの引数を除きますか?では、メモ帳でファイルを開くか、それとも別のものにしますか?
12


3

Windowsでショートカットを使用する場合と同じ問題だと思います...これを試してください:

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

申し訳ありませんが、それも機能しません。これを反映するように質問を編集しました。
Lasse V. Karlsen、

私はWindowsのみではなく'より引用のために、」使用すると思います。これはおそらく、仕事あなたがこれを変更する場合はしかし、あなたはまだ問題に実行されますと、あなたが埋め込まれている場合は、引用符など。。
ブライアン

両方かかったと思いましたが、おそらくあなたは正しいです。私はそれが(シェルで)二重引用符で動作することを知っています。
Matthew Scharley、2008年

+1これは最高の1つ

0

パス(path = '/home/<you>/<first-path-section> <second-path-section>')の間にスペースがあるDjango Webサーバー(Linux)を実行する場合は、次のようにします。

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:\ Program Files \ Git \ git-bash.exe"#mycaseのアプリケーションファイルパスGITBASH os.startfile(GitPath)

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.