【问题标题】:Handle infinite loop function inside a thread处理线程内的无限循环函数
【发布时间】:2019-09-27 01:19:07
【问题描述】:

我正在做一个 python 2.7 插件,可以在 android 设备上执行一些测试。

我的一个测试使用 adb 命令,但该命令在某些设备上执行无限循环。

命令:adb shell am start -W -a android.intent.action.VOICE_COMMAND

预期输出:

Starting: Intent { act=android.intent.action.VOICE_COMMAND }
Status: ok
Activity: com.google.android.googlequicksearchbox/com.google.android.apps.gsa.velour.dynamichosts.TransparentVelvetDynamicHostActivity
ThisTime: 241
TotalTime: 659
WaitTime: 684
Complete

在我的大多数设备上,这个命令运行良好,但在其他设备上它循环并且永远不会返回任何东西。

我尝试将此命令调用到一个线程中,但即使这样做我也无法弄清楚如何在超时后终止该线程。

这是我已经尝试过的(参见this),但这些都不起作用,因为线程被锁定在无限循环调用中,所以我无法检查是否在这个线程中设置了“结束”变量,也不处理事件。

有没有办法在一段时间后用这样的东西杀死这个线程? =>

endtime = time.time() + 20
t1 = MyThread(my_func, "my_args", "my_args2")
while True:
    if time.time() > endtime:
        end_thread(t1) # or t1.end() or idk
    else:
        time.sleep(1)

【问题讨论】:

  • This post 建议将线程包装在子进程中,以便可以安全地终止它们。
  • 使用多处理不是我的插件的解决方案,它在设备上有一些异常行为。这个 python 模块包含大约 50 个在 android 设备上执行测试的子插件。在我的插件上使用多处理曾经对其他插件进行错误的一些测试。
  • 你还没有向我们展示你是如何开始adb的。如果您使用的是 subprocess 模块,那么 Python 3 中有一个 timeout 选项(在 Python 2 的 subprocess32 反向移植中提供了相同的功能)。
  • 我正在使用 adb.shell(args) 启动 adb。这是我程序中的一个模块,专为 adb 的各种用途而设计。 adb.shell 使用另一个模块,command.py,在这个模块中,adb 命令使用 subprocess.Popen() 执行到子进程中。直到现在我才知道 adb.shell 方法实际上使用了子进程。我会尝试为此添加某种超时。

标签: python python-2.7 adb


【解决方案1】:

解决了我的问题。

我这样使用子进程:

模块命令.py

import subprocess
# [...]
def execute(cmd, args=None, display_cmd=False, disable_out=False, disable_error=False, no_wait=False, is_shell=False):
    if cmd is None:
        return None

    cmd_args = [cmd]

    if args is not None:
        for arg in args:
            cmd_args.append(str(arg))

    if display_cmd:
        str_cmd = None
        for arg in cmd_args:
            if str_cmd is None:
                str_cmd = str(arg)
            else:
                str_cmd = str_cmd + " " + str(arg)
        Logs.instance().debug(str_cmd)

    std_out = subprocess.PIPE
    if disable_out:
        std_out = DEVNULL

    if no_wait:
        subprocess.Popen(cmd_args, stdin=None, stdout=None, stderr=None, shell=is_shell)
        return None
    elif disable_error:
        p = subprocess.Popen(cmd_args, stdout=std_out, stderr=DEVNULL, shell=is_shell)
    else:
        p = subprocess.Popen(cmd_args, stdout=std_out, shell=is_shell)

    if disable_out:
        return None
    else:
        out = p.stdout.read()
        return out

模块 adb.py

def shell(cmd, no_wait=False):
    data = cmd.split()
    if data[0] != "shell":
        data.insert(0, "shell")
    if no_wait:
        result = command.execute("adb", data, no_wait=True)
    else:
        result = command.execute("adb", data)
    return result

我的插件

def _my_test(self, x, y):
    result = adb.shell("shell am start -W -a android.intent.action.VOICE_COMMAND", no_wait=True)
    if not result:
        # handle
    else:
        # [...]

谢谢,希望有一天能帮到别人

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2023-02-09
    • 2020-07-01
    • 2020-03-17
    • 2014-11-12
    • 1970-01-01
    • 1970-01-01
    • 2016-12-27
    • 1970-01-01
    相关资源
    最近更新 更多