23

仮想マシンの起動/シャットダウン/登録/登録解除アクションの自動化を可能にする、vmware 実行可能ファイルを実行するラッパー スクリプトに取り組んでいます。サブプロセスを使用して実行可能ファイルの呼び出しを処理しようとしていますが、実行可能ファイルのパスと実行可能ファイルのパラメーターのスペースがサブプロセスによって正しく処理されていません。以下はコードの一部です。

vmrun_cmd = r"c:/Program Files/VMware/VMware Server/vmware-cmd.bat"
def vm_start(target_vm):
    list_arg = "start"
    list_arg2 = "hard"
    if vm_list(target_vm):
            p = Popen([vmrun_cmd, target_vm, list_arg, list_arg2],   stdout=PIPE).communicate()[0]
            print p
    else:
            vm_register(target_vm)
            vm_start(target_vm)
def vm_list2(target_vm):
    list_arg = "-l"
    p = Popen([vmrun_cmd, list_arg], stdout=PIPE).communicate()[0]
    for line in p.split('\n'):
            print line

vm_list2 関数を呼び出すと、次の出力が得られます。

$ ./vmware_control.py --list                                                
C:\Virtual Machines\QAW2K3Server\Windows Server 2003 Standard Edition.vmx
C:\Virtual Machines\ubunturouter\Ubuntu.vmx
C:\Virtual Machines\vacc\vacc.vmx
C:\Virtual Machines\EdgeAS-4.4.x\Other Linux 2.4.x kernel.vmx
C:\Virtual Machines\UbuntuServer1\Ubuntu.vmx
C:\Virtual Machines\Other Linux 2.4.x kernel\Other Linux 2.4.x kernel.vmx
C:\Virtual Machines\QAClient\Windows XP Professional.vmx

path-to-vm パラメーターを必要とする vm_start 関数を呼び出すと、次の出力が得られます。

$ ./vmware_control.py --start "C:\Virtual Machines\ubunturouter\Ubuntu.vmx"
'c:\Program' is not recognized as an internal or external command,
operable program or batch file.

どうやら、スペースが埋め込まれた 2 番目のパラメーターの存在は、サブプロセスが最初のパラメーターを解釈する方法を変更しています。これを解決する方法について何か提案はありますか?

python2.5.2/cygwin/winxp

4

10 に答える 10

8

パスにスペースがある場合、それらを正しく解釈するために私が見つけた最も簡単な方法はこれです。

subprocess.call('""' + path + '""')

なぜ正確に二重引用符が必要なのかわかりませんが、それが機能します。

于 2009-04-30T13:41:10.677 に答える
4
'c:\Program' is not recognized as an internal or external command,
operable program or batch file.

このメッセージを受け取るには、次のいずれかです。

  1. 使用shell=True:

    vmrun_cmd = r"c:\Program Files\VMware\VMware Server\vmware-cmd.bat"
    subprocess.Popen(vmrun_cmd, shell=True)
    
  2. コードの他の部分で vmrun_cmd を変更する

  3. vmware-cmd.bat 内の何かからこのエラーを取得する

試すこと:

  • Python プロンプトを開き、次のコマンドを実行します。

    subprocess.Popen([r"c:\Program Files\VMware\VMware Server\vmware-cmd.bat"])
    

それが機能する場合、引用の問題は問題外です。そうでない場合は、問題を特定しました。

于 2009-04-30T01:46:59.037 に答える
3

リスト引数の処理を行っている list2cmdline() は、文字列に二重引用符が含まれていない限り、文字列引数を空白で分割すると思います。だから私は期待するだろう

vmrun_cmd = r'"c:/Program Files/VMware/VMware Server/vmware-cmd.bat"'

あなたが望むものになるために。

target_vm他の引数 ( など) も、それぞれがコマンド ラインに提示する個別の引数を表しているという前提で、二重引用符で囲む必要があります。何かのようなもの

r'"%s"' % target_vm

(例えば)合うはずです。

list2cmdline のドキュメントを参照してください

于 2009-04-30T02:00:13.203 に答える
2

MS Windows 上の Python では、subprocess.Popen クラスが CreateProcess API を使用してプロセスを開始します。CreateProcess は、引数の配列のようなものではなく文字列を取ります。Python は、subprocess.list2cmdline を使用して、引数のリストを CreateProcess の文字列に変換します。

もし私があなただったら、subprocess.list2cmdline(args) が何を返すかを見るでしょう (ここで、args は Popen の最初の引数です)。最初の引数を引用符で囲んでいるかどうかを確認するのは興味深いでしょう。

もちろん、この説明は Cygwin 環境には当てはまらない場合があります。

とはいえ、私は MS Windows を持っていません。

于 2009-04-30T04:11:00.313 に答える
1

1 つの問題は、コマンドが引用符で囲まれ、スペースが含まれていない場合、シェルが混乱する可能性があることです。

だから私はこれを行います:

if ' ' in raw_cmd:
    fmt = '"%s"'
else:
    fmt = '%s'

cmd = fmt % raw_cmd
于 2009-06-14T15:09:33.527 に答える
0

これは私たちの最後の 3 つの問題にとってはかなり難しい問題でした....これまでに述べたことは何も機能しませんでした。r"" や Popen をリストで使用することもできませんでした。最終的にうまくいったのは、フォーマット文字列と r"" の組み合わせでした。だから私の解決策はこれです:

subprocess.Popen("{0} -f {1}".format(pathToExe, r'"%s"' % pathToVideoFileOrDir))

ここで、変数 pathToExe と pathToVideoFileOrDir の両方のパスに空白が含まれています。フォーマットされた文字列内で \" を使用しても機能せず、最初のパスが正しく検出されないという同じエラーが発生しました。

于 2016-04-08T14:48:01.507 に答える
-1

2つのこと

1)

おそらく Pipe を使用したくないでしょう。サブプログラムの出力が 64KB を超えると、プロセスがクラッシュする可能性があります。 http://thraxil.org/users/anders/posts/2008/03/13/Subprocess-Hanging-PIPE-is-your-enemy/

2) Subprocess.Popen にはキーワード引数 shell があり、シェルが引数を解析しているかのようになり、shell=True を設定すると、必要なことが行われます。

于 2009-04-30T01:49:23.947 に答える
-2

なぜr""を使っているのですか?最初の「r」を削除すると、スペースを含む可能性のある標準の文字列として扱われると思います。Python は、シェルに送信するときに文字列を適切に引用する必要があります。

于 2009-04-30T01:22:40.157 に答える
-2

嫌いなものはこちら

vmrun_cmd = r"c:/Program Files/VMware/VMware Server/vmware-cmd.bat"

コマンド自体の名前にスペースが含まれているため、シェルが困惑しています。したがって、「'c:\Program' は、内部コマンドまたは外部コマンド、操作可能なプログラムまたはバッチ ファイルとして認識されません。」

オプション 1 -- .BAT ファイルを別の場所に置きます。実際、すべての VMWare を別の場所に置いてください。ルールは次のとおり です。「Program Files」ディレクトリを何にも使用しないでください。 それはただ間違っています。

vmrun_cmdオプション 2 --値を引用する

vmrun_cmd = r'"c:/Program Files/VMware/VMware Server/vmware-cmd.bat"'
于 2009-04-30T13:19:59.277 に答える