Android 为什么我运行adb shell monkey命令的python脚本会因大量事件而崩溃?
我编写了一个小python函数,它使用subprocess.popen运行adb shell monkey-p-v命令和adb logcat命令。对于大于100的值,这个程序崩溃,我不知道为什么 这是monkey_runner.pyAndroid 为什么我运行adb shell monkey命令的python脚本会因大量事件而崩溃?,android,python,subprocess,adb,Android,Python,Subprocess,Adb,我编写了一个小python函数,它使用subprocess.popen运行adb shell monkey-p-v命令和adb logcat命令。对于大于100的值,这个程序崩溃,我不知道为什么 这是monkey_runner.py import os, subprocess def run_monkey_process(package, num_commands): monkeycmd = "adb shell monkey -p " + package + " -v " +
import os, subprocess
def run_monkey_process(package, num_commands):
monkeycmd = "adb shell monkey -p " + package + " -v " + num_commands
monkeyprocess = subprocess.Popen(monkeycmd, stdout=subprocess.PIPE)
logcatcmd = "adb logcat"
logcatprocess = subprocess.Popen(logcatcmd, stdout=subprocess.PIPE)
monkeystring = monkeyprocess.communicate(input=None)[0]
logcatstring = logcatprocess.communicate(input=None)[0]
monkeyreturncode = monkeyprocess.poll()
logcatreturncode = logcatprocess.poll()
if(monkeyreturncode >=0):
monkeyprocess.kill()
logcatprocess.kill()
return monkeystring, logcatstring
else:
print 'command failure'
return 'you', 'fail'
我也可以把我的gui代码放在这里,但没什么特别的
这是stacktrace
Exception in Tkinter callback
Traceback (most recent call last):
File "C:\Python27\lib\lib-tk\Tkinter.py", line 1470, in __call__
return self.func(*args)
File "C:\Users\brandon.dalesandro\Desktop\Zonar\mankey\monkey_runner_gui.py", line 25, in goCallBack
returned = run_monkey_process(package, num)
File "C:\Users\brandon.dalesandro\Desktop\Zonar\mankey\monkey_runner.py", line 8, in run_monkey_process
logcatstring = logcatprocess.communicate(input=None)[0]
File "C:\Python27\lib\subprocess.py", line 798, in communicate
stdout = _eintr_retry_call(self.stdout.read)
File "C:\Python27\lib\subprocess.py", line 478, in _eintr_retry_call
return func(*args)
KeyboardInterrupt
这可能是你的问题,但如果没有更多的信息,很难判断
您已经为子流程指定了一个管道,但直到子流程完成后才读取它。文档中的说明解释了为什么这是不好的:
这将在使用stdout=PIPE
和/或stderr=PIPE
时死锁,并且子进程生成足够多的输出到管道,从而阻止等待OS管道缓冲区接受更多数据。使用communicate()
来避免这种情况
当没有足够的数据填充管道缓冲区时,它将适用于少量命令,但挂起用于较大数量的命令,这是非常合理的
循环使用poll
而不是调用wait
没有任何帮助;它所做的只是毫无理由地消耗100%的CPU。你还是没在看烟斗里的东西
而在流程完成后调用通信
,也无济于事。如果管道已满,子进程将永远被阻塞,poll
将永远不会返回值,您甚至无法进行通信
由于通信
已经有了自己的等待
,因此您真正需要的就是:
monkeyprocess = subprocess.Popen(monkeycmd, stdout=subprocess.PIPE, bufsize=1)
monkeystring = monkeyprocess.communicate(input=None)[0]
returncode = monkeyprocess.returncode
“崩溃”是什么意思?它是否真的隔离故障和转储核心?或者打印出异常回溯?或者返回失败?这不是您的问题,但是…您永远不应该循环使用monkeyprocess.poll()
;这将与只调用monkeyprocess.wait()
具有相同的效果,只是为了无故消耗100%的CPU。(当我们这样做的时候,千万不要做==None
,do就是None
,如果和处于状态时,在周围放置额外的参数会使代码更难阅读。)此外,在终止后调用kill
也没有好的理由。在POSIX上,如果SIGTERM
没有终止进程,SIGKILL
可能没有帮助。在Windows上,它们都做完全相同的事情。在kill之后调用communicate
是没有用的,因为同样的原因,在循环poll
或调用wait
之后也是没有用的。当我说崩溃时,我的意思是它会一直挂起,直到我用任务管理器杀死它。好的,“挂起”或“冻结”与“崩溃”是完全不同的,如果你使用正确的术语而不是让人们猜测,你会得到更好的答案。不管怎么说,如果你只是在等待,很可能是在poll
的循环中,所以我的答案会解决它。(但最好知道它挂起的位置,只需在bash/cmd shell中运行它,使用control-C停止它,并查看从打印出来的键盘中断
的回溯即可看到。)感谢您的回答。我如何收集adb信息,而不填充管道?我可以定期将其添加到字符串或文件中并清除管道吗?为了避免阻塞管道,您需要循环proc.stdout.read(n)
,并确保不执行任何阻塞操作(如旋转proc.poll()
)以阻止您以数据进入的速度读取数据)。但是,如果您只需通过调用communicate
以简单的方式进行操作,它已经为您解决了这一问题。这就是为什么文档建议尽可能使用沟通
,而不是自己尝试。