web-dev-qa-db-ja.com

Python subprocess.callはプロセスがブレンダーを完了するのを待っていません

私はpythonスクリプトをブレンダーに持っています

subprocess.call(os.path.abspath('D:/Test/run-my-script.sh'),Shell=True)

このシェルスクリプトに依存する他の多くのコードが続きます。完了するのを待たないのですが、どうしてですか?以下のように、Popenの代わりにcallを使用してみました。

_p1 = subprocess.Popen(os.path.abspath('D:/Test/run-my-script.sh'),Shell=True)
p1.wait()
_

そして私はcommincateを使ってみましたが、それでもうまくいきませんでした:

_p1 = subprocess.Popen(os.path.abspath('D:/Test/run-my-script.sh'),Shell=True).communicate()
_

このシェルスクリプトはMacOS(パスの変更後)で適切に機能し、subprocess.call(['sh', '/userA/Test/run-my-script.sh'])を使用するときに待機します

しかし、Windowsではこれが起こります。Blenderで以下のpythonスクリプトを実行し、サブプロセス行に到達したら_Git bash_を開いてシェルスクリプトを実行しますが、blenderは実行しません。 Git Bashが完了するのを待たずに、コンソールでHelloを出力するだけです。

_import bpy
import subprocess
subprocess.call(os.path.abspath('D:/Test/run-my-script.sh'),Shell=True)
print('Hello')
_
12
Tak

subprocess.callを使用して、まさにそれを行うことができます。

サブプロセス。callargs、*、stdin = None、stdout = None、stderr = None、Shell = False、timeout =なし

Argsで記述されたコマンドを実行します。コマンドが完了するのを待ってから、returncode属性を返します。

編集:私は何が起こっているのかについての直感を持っていると思います。 MacはBashをそのまま使用できるので(少なくとも機能的に同等のもの)、Macではコマンドが機能しますが、Windowsでは ".sh "ファイルを作成し、代わりにGit Bashを起動します。これは、起動時にいくつかのフォークを実行すると思います。

このPythonthinkとスクリプトが実行されたため、PIDはなくなっています。

私があなただったら、こうします。

  • tempfile モジュールを使用して、「起動」スクリプト内に存在しない一意の絶対パスを生成します。
  • スクリプトを起動するときに、作成したパスを引数として渡します。
  • スクリプトが開始したら、パスにファイルを作成します。完了したら、ファイルを削除します。
  • 起動スクリプトは、そのファイルの作成と削除を監視して、スクリプトのステータスを示す必要があります。

うまくいけば、それは理にかなっています。

6
joeb

Popen.communicate APIを使用できます。

p1 = subprocess.Popen(os.path.abspath('D:/Test/run-my-script.sh'),Shell=True)
sStdout, sStdErr = p1.communicate()

コマンド

Popen.communicate(input=None, timeout=None)

プロセスとの対話:stdinにデータを送信します。ファイルの終わりに達するまで、stdoutおよびstderrからデータを読み取ります。プロセスが終了するのを待ちます。

4
Pankaj

subprocess.PopenおよびPopen.wait

process = subprocess.Popen(['D:/Test/run-my-script.sh'],Shell=True, executable="/bin/bash")
process.wait()

Popenの代わりに check_call() を使用することもできます。

2
Fran Raga

subprocess.runはデフォルトで、プロセスが完了するまで待機します。

2
Grr

Runコマンドが失敗する場合があります。これは私の回避策です:

def check_has_finished(pfi, interval=1, timeout=100):
    if os.path.exists(pfi):
        if pfi.endswith('.nii.gz'):
            mustend = time.time() + timeout
            while time.time() < mustend:
                try:
                    # Command is an ad hoc one to check if the process  has finished.
                    subprocess.check_output('command {}'.format(pfi), Shell=True)
                except subprocess.CalledProcessError:
                    print "Caught CalledProcessError"
                else:
                    return True
                time.sleep(interval)
            msg = 'command {0} not working after {1} tests. \n'.format(pfi, timeout)
            raise IOError(msg)
        else:
            return True
    else:
        msg = '{} does not exist!'.format(pfi)
        raise IOError(msg)
1
SeF

次のようにos.systemを使用できます。

import bpy
import os
os.system("sh "+os.path.abspath('D:/Test/run-my-script.sh'))
print('Hello')
1
A STEFANI

ひどい試みですが、シェルを管理者として実行しながら、ブレンダーを通常のユーザーとして、またはその逆を実行していますか?

一言で言えば、Windows UACは管理者と通常のユーザーの間の一種の隔離された環境であるため、このようなランダムな癖が発生する可能性があります。残念ながら、これのソースを思い出せません。最も近いのは this です。

私の問題はあなたの問題の正反対でした、wait()は無限ループで立ち往生しました。私のpython REPLが管理者から発行されたためです。シェルであり、通常のユーザーサブプロセスの状態を読み取ることができませんでした。通常のユーザーシェルに戻すと、修正されました。このUAC snafuを使用するのは初めてではありません。

0
Gruber