100次迭代后无法为子进程(运行adb shell命令的进程)提供输入

时间:2013-08-19 23:03:05

标签: python subprocess

我想为adb(android debug bridge)shell运行压力测试。 (adb shell在这方面只是Android手机提供的命令行工具)。

我从python创建一个子进程,在这个子进程中我执行'adb shell'命令。有一些命令必须给这个子进程,我通过子进程的stdin提供。

一切似乎都很好,但是当我进行压力测试时。在大约100次迭代之后,我给stdin的命令没有到达子进程。如果我在单独的终端中运行命令它运行正常。但问题在于这个stdin。

谁能告诉我我做错了什么。以下是代码示例

class ADB():
def __init__(self):
    self.proc = subprocess.Popen('adb shell', stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, shell=True,bufsize=0)


def provideAMcommand(self, testParam):
    try:
        cmd1 = "am startservice -n com.test.myapp/.ADBSupport -e \"" + "command" + "\" \"" + "test" + "\""  
        cmd2 = " -e \"" + "param" + "\"" + " " + testParam
        print cmd1+cmd2
        sys.stdout.flush()
        self.proc.stdin.write(cmd1 + cmd2 + "\n")
    except:
        raise Exception("Phone is not Connected to Desktop or ADB is not available \n")

2 个答案:

答案 0 :(得分:1)

如果它适用于前几个命令但稍后阻塞,那么您可能忘记从self.proc.stdout读取可能导致(如文档警告的)OS管道缓冲区填满并阻止子进程。

要丢弃输出,请将其重定向到os.devnull

import os
from subprocess import Popen, PIPE, STDOUT

DEVNULL = open(os.devnull, 'wb')
# ...
self.proc = Popen(['adb', 'shell'], stdin=PIPE, stdout=DEVNULL, stderr=STDOUT)
# ...
self.proc.stdin.write(cmd1 + cmd2 + "\n")
self.proc.stdin.flush()

对于基于对话框的交互,pexpect module可能是更好的工具(如果你想同时读/写)。

答案 1 :(得分:0)

IN provideAMcommand您正在写入并刷新主进程的标准输出。这不会向您使用Popen创建的子进程的stdin发送任何内容。以下代码创建了一个新的bash子进程,有点像__init__中的代码:

import subprocess as sp
cproc = sp.Popen("bash", stdin=sp.PIPE, stdout=sp.PIPE, stderr=sp.PIPE, shell=True)

现在,与子进程通信的最简单方法如下:

#Send command 'ls' to bash.
out, err = cproc.communicate("ls")

这会将文本“ls”和EOF发送给bash(等于运行一个只包含文本“ls”的bash脚本)。 Bash将执行ls命令然后退出。 bash或ls写入stdout和stderr的任何内容将分别以变量outerr结尾。我没有使用过adb shell,但我觉得它在这方面表现得像bash。

如果您只是希望子进程打印到终端,请不要指定stdout的{​​{1}}和stderr个参数。

您可以检查子项的退出代码,如果异常非零(表示错误),则引发异常:

Popen