3

こんにちは、subprocess.Popen を使用しているときに stdout の読み取りに問題があります。

daniel@desktop:~$ python -V
Python 2.7.3

コードはこちら:(コメント付きのコードは私が試したものです)

import subprocess

RUN = './hlds_run -game cstrike -maxplayers 11'

p = subprocess.Popen(RUN.split(), shell=False, stdout=subprocess.PIPE, stdin=subprocess.PIPE, stderr=subprocess.PIPE)

while 1:
    try:
        out = p.stdout.readline()
        #if out == '':
        #   out = p.stdout.read()
        #p.stdout.flush()
    except: 
        p.terminate()
        break

    try:
        err = p.stderr.readline()
        #if err == '':
        #   err = p.stderr.read()
        #p.stderr.flush()
    except:
        p.terminate()
        break
    if out != '':
        print out.rstrip()

    if err != '':
        print err.rstrip()


    #print '\n' #constantly prints new lines until "Calling BreakpadMiniDumpSystemInit."

これは、サーバーに接続して切断したときに得られる出力です。

daniel@desktop:~/hlds$ python hlds.py 
Auto detecting CPU
Using breakpad crash handler
Using Pentium II Optimised binary.
Setting breakpad minidump AppID = 10
Auto-restarting the server on crash
Forcing breakpad minidump interfaces to load

Looking up breakpad interfaces from steamclient
Console initialized.
Calling BreakpadMiniDumpSystemInit
scandir failed:/home/daniel/hlds/./valve/SAVE
Installing breakpad exception handler for appid(10)/version(5447)
scandir failed:/home/daniel/hlds/./platform/SAVE
Looking up breakpad interfaces from steamclient
Protocol version 48
Calling BreakpadMiniDumpSystemInit

while ループは次の後にロックします。

Calling BreakpadMiniDumpSystemInit.

しかし、サーバーはまだ実行されており、接続したり、コマンドを実行したりできます...


私が実行した場合:

 ./hlds_run -game cstrike -maxplayers 11 >> stdout.log 2>&1

stdout.log に次の出力が表示されます。

daniel@desktop:~/hlds$ cat stdout.log 
Auto detecting CPU
Using Pentium II Optimised binary.
Auto-restarting the server on crash

Console initialized.
Using breakpad crash handler
Setting breakpad minidump AppID = 10
Forcing breakpad minidump interfaces to load
Looking up breakpad interfaces from steamclient
Calling BreakpadMiniDumpSystemInit
Installing breakpad exception handler for appid(10)/version(5447)
scandir failed:/home/daniel/hlds/./valve/SAVE
scandir failed:/home/daniel/hlds/./platform/SAVE
Protocol version 48
Exe version 1.1.2.6/Stdio (cstrike)
Exe build: 14:06:24 Sep 23 2011 (5447)
STEAM Auth Server
Server IP address 127.0.1.1:27015
couldn't exec listip.cfg
couldn't exec banned.cfg
Looking up breakpad interfaces from steamclient
Calling BreakpadMiniDumpSystemInit
scandir failed:/home/daniel/hlds/./valve/SAVE
scandir failed:/home/daniel/hlds/./platform/SAVE

Could not establish connection to Steam servers.
Reconnected to Steam servers.
   VAC secure mode is activated.
ERROR: couldn't open custom.hpk.
JAMES HETFIELD : hello!
Dropped JAMES HETFIELD from server
Reason:  Client sent 'drop'
Sat Apr 14 00:10:54 CEST 2012: Server Quit

ただし、2>&1 を実行しない場合でも、この出力は stdout に表示され、残りは stdout.log に表示されます。

daniel@desktop:~/hlds$ ./hlds_run -game cstrike -maxplayers 11 >> stdout.log
Using breakpad crash handler
Setting breakpad minidump AppID = 10
Forcing breakpad minidump interfaces to load
Looking up breakpad interfaces from steamclient
Calling BreakpadMiniDumpSystemInit
Installing breakpad exception handler for appid(10)/version(5447)
Looking up breakpad interfaces from steamclient
Calling BreakpadMiniDumpSystemInit

サブプロセス学習体験としてサーバーマネージャーとディスパッチャーを作成しようとしています:]

すべての助けに感謝します!:)

4

2 に答える 2

1

パイプの1つがデータでいっぱいになり、サブプロセスがブロックされ、Pythonプロセスが他のパイプから行を読み取ろうとしてブロックされ、デッドロックが発生します。パイプでブロッキング読み取りを行う代わりに、何らかのポーリング (select/poll/epoll) を使用することをお勧めします。

簡単なハックは、while ループでノンブロッキング読み取りを行うことですが、それは Python プロセスが大量の CPU を使用することにつながります。

問題を非ハッキーな方法で解決する方法の詳細については、 selectモジュールのドキュメントを参照してください。

于 2012-04-13T23:31:14.003 に答える
0

selectを使用してこれを解決できましたか?非ブロックであっても SRCDS を開始すると、「Calling BreakpadMiniDumpSystemInit」を通過しないことがわかりました。

p = subprocess.Popen(cmd, shell=False, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, close_fds=True)
fcntl.fcntl(p.stdout, fcntl.F_SETFL, fcntl.fcntl(p.stdout, fcntl.F_GETFL) | os.O_NONBLOCK)
print p.stdout.read()

これは、「BreakpadMiniDumpSystemInit」メッセージまで出力し、さらに read() を呼び出すと、p.stdin に何かが書き込まれるまで「リソースが一時的に利用できません」とスローされます。

于 2012-06-03T14:50:29.577 に答える