关于python3.x:如何创建一个超时后不会被kill的python子进程

7次阅读

共计 2524 个字符,预计需要花费 7 分钟才能阅读完成。

在 subprocess 之前,创立一个新过程的形式有很多种,如 os.system()、os.spawn* 办法等。为了对立创立过程的形式,python 社区提议应用 subprocess 模块作为创立过程的规范形式,用来替换 os.system 和 os.spawn* 等形式。

subprocess 模块的应用

subprocess.run

办法签名如下

subprocess.run(*args*, *** , *stdin=None*, *input=None*, *stdout=None*, *stderr=None*, *capture_output=False*, *shell=False*, *cwd=None*, *timeout=None*, *check=False*, *encoding=None*, *errors=None*, *text=None*, *env=None*, *universal_newlines=None*, ***other_popen_kwargs*)

run 办法是创立过程的举荐办法,只有 run 办法无奈满足需要的时候才思考应用 popen 办法。run 会梗塞式地执行 args 参数提供的命令,直到命令执行完结或者超时。args 能够是字符串数组或者字符串,当 args 为字符串时,shell 参数必须为 True。

我想创立一个子过程,应用 adb install 命令给 vivo/oppo/xiaomi 手机装置 app,然而 vivo/oppo/xiaomi 手机会弹出二次确认窗口,如果不进行点击操作,则无奈装置 App。所以我就想创立一个子过程,超时后再接着由 UI 自动化的形式来点击确认按钮。这就要求超时后装置过程不能退出。run 办法尽管有 timeout 参数,然而子过程会在超时被 kill 掉。

以下动画演示了手动装置 app 时须要二次确认,手动点击持续装置后,能够在控制台看到以下输入

Perform Streamed Install 
Success

证实曾经装置胜利了。

 

以下动画演示了应用 run 命令,超时后装置过程被 kill 掉了,在控制台无奈看到胜利装置的日志输入。二次确认后,装置过程就不见了。

对应的代码:

import subprocess

if __name__ == '__main__':

    proc=subprocess.run('adb install -g -r -t app-uiautomator.apk', shell=True, timeout=10, capture_output=True)

 

subprocess.Popen

subprocess 模块里过程的创立和治理都是 Popen 类解决的,它让开发者非常灵活地解决一些不常见的场景。
 

-   *class* subprocess.Popen(*args*, *bufsize=- 1*, *executable=None*, *stdin=None*, *stdout=None*, *stderr=None*, *preexec_fn=None*, *close_fds=True*, *shell=False*, *cwd=None*, *env=None*, *universal_newlines=None*, *startupinfo=None*, *creationflags=0*, *restore_signals=True*, *start_new_session=False*, *pass_fds=()* , *** , *group=None*, *extra_groups=None*, *user=None*, *umask=- 1*, *encoding=None*, *errors=None*, *text=None*, *pipesize=- 1*, *process_group=None*)

Popen 类有以下几个办法:

  • Popen.communicate

    Popen.communicate(*input=None*, *timeout=None*)

    communicate()返回一个元组(stdout_data, stderr_data),如果 Popen 指定了 text 模式,stdout_data 将为字符串,否则为 byte

  1. input 向规范输出发送信息
  2. timeout 如果进行在 timeout 指定的工夫之内没有完结,则抛出一个 TimeoutExpired 异样,且过程不会被杀死

抛出异样后能够持续从新调用 communicate()

* Popen.send_signal(signal) 向子过程发送信号

* Popen.terminate() 进行子过程

* Popen.poll() 查看过程是否完结,没有完结返回 None,否则返回执行状态的数值

 Popen.wait(timeout=None*) 期待子过程执行完结,如果 timeout 指定的工夫之后过程没有完结,则抛出 TimeoutExpired

 在我的执行场景中,须要应用 communicate 办法,以下是应用 Popen 类调用 adb 命令装置 app 的动画展现,超时后,手动点击持续装置,app 最终装置胜利。

对应的代码如下:


import subprocess

from subprocess import TimeoutExpired
 

if __name__ == '__main__':

    try:

        proc=subprocess.Popen('adb install -g -r -t app-uiautomator.apk', shell=True, text=True, stdout=subprocess.PIPE)

        stdout,errs = proc.communicate(timeout=10)

        print(f'stdout1:{stdout}')

    except TimeoutExpired as te:

        print('timeout')

        stdout,errs = proc.communicate()

        print(f'stdout2:\n{stdout}')

这样的话,我的目标就达到了。

参考文档

  • pep-0324 subprocess 模块

后语

如果大家喜爱我写的文章,欢送大家点赞、珍藏、评论留言或者私信与我交换。

正文完
 0