【问题标题】:Not able to give inputs to subprocess(process which runs adb shell command) after 100 iterations100 次迭代后无法为子进程(运行 adb shell 命令的进程)提供输入
【发布时间】:2013-08-19 23:03:04
【问题描述】:

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

我从 python 创建一个子进程,并在这个子进程中执行“adb shell”命令。有一些命令必须提供给这个子进程,我通过子进程的标准输入提供这些命令。

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

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

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")

【问题讨论】:

  • 给出你的代码;没有命令到达子进程。
  • 我已经添加了这一行。我错误地删除了这一行。

标签: python subprocess


【解决方案1】:

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

要丢弃输出,请将其重定向到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 可能是基于对话的交互的更好工具(如果您希望同时读取/写入间歇性)。

【讨论】:

  • 我会检查这个并让你知道这是否有效。我觉得这就是正在发生的事情。提前致谢
【解决方案2】:

IN provideAMcommand 您正在写入并刷新主进程的标准输出。这不会向您使用Popen 创建的子进程的标准输入发送任何内容。下面的代码创建了一个新的 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 的任何内容都将分别在变量 out 和 err 中结束。我没有使用过 adb shell,但我猜它在这方面表现得像 bash。

如果您只想让您的子进程打印到终端,请不要将stdout 和stderr 参数指定给Popen。

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

if (cproc.returncode != 0):
     raise Exception("Child process returned non-zero exit code")

【讨论】:

  • 我在provideAMcommand 中又添加了一行。我错误地删除了该行,我正在为 Windows 运行它。
猜你喜欢
  • 2021-05-15
  • 1970-01-01
  • 2014-11-10
  • 1970-01-01
  • 2011-10-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-03-16
相关资源
最近更新 更多