Skip to main content
 首页 » 编程设计

python之子进程 popen stdout 锁定

2025年05月04日41birdshome

您好,在使用 subprocess.Popen 时,标准输出读取有一些问题

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 

尝试创建服务器管理器和调度程序作为子进程学习经验:]

感谢所有帮助! :)

请您参考如下方法:

发生的情况是其中一个管道被数据填满,因此在您的 python 进程被阻止尝试从另一个管道读取一行时阻塞子进程,从而导致死锁。您可能想使用某种轮询(select/poll/epoll)而不是在管道上进行阻塞读取。

一个快速的破解方法是在你的 while 循环中进行非阻塞读取,但这会导致你的 python 进程使用大量 CPU。

查看 select 的文档模块以获取有关以非 hacky 方式解决问题的更多信息。