如何使用asyncio连续读取进程并在超时后将其杀死

时间:2018-07-18 14:21:59

标签: python python-asyncio

我想使用asyncio连续读取进程,直到我稍后将其停止。我已经尝试了很多东西,但是不知道该怎么做。

这是一次似乎根本不关心kill的尝试

import io
import asyncio

class Foo():

    async def run(self):
        proc = await asyncio.create_subprocess_shell('ping www.google.de', stdout=asyncio.subprocess.PIPE)
        await asyncio.gather(self.run_proc(proc), self.kill_proc(proc))

    async def run_proc(self, proc):
        while True:
            await asyncio.sleep(0)
            line = await proc.stdout.readline()
            print(line)

    async def kill_proc(self, proc):
        await asyncio.sleep(1000)
        print("meh")
        proc.kill()


f = Foo()
loop = asyncio.get_event_loop()
loop.run_until_complete(f.run())

更新:以下是工作代码,其中包含来自user4815162342的反馈

import io
import asyncio

class Foo():

    async def run(self):
        proc = await asyncio.create_subprocess_exec('ping', 'www.google.de', stdout=asyncio.subprocess.PIPE)
        await asyncio.gather(self.run_proc(proc), self.kill_proc(proc))

    async def run_proc(self, proc):
        while True:
            line = await proc.stdout.readline()

            if line == b'':
                break

            print(line)

    async def kill_proc(self, proc):
        await asyncio.sleep(1)
        print("meh")
        proc.kill()


f = Foo()
loop = asyncio.get_event_loop()
loop.run_until_complete(f.run())

1 个答案:

答案 0 :(得分:1)

  

这是一次似乎根本不关心kill的尝试

您真的耐心等待16分钟40秒来调用kill吗?如果我将await asyncio.sleep(1000)更改为await asyncio.sleep(2),该过程确实会在两秒钟内被杀死。

编辑,我现在已经在其他系统上进行了尝试,并重现了该问题。事实证明,proc.kill()杀死了shell进程(等待ping完成),但没有杀死ping进程本身。跨平台的解决方法(您已经discovered)是使用create_subprocess_exec,这样可以避免使用shell。

另外:

  • ping被杀死时,run_proc最终陷入无限循环,因为该循环缺少诸如if line == b'': break之类的东西。

  • 您不需要await asyncio.sleep(0)readline()已经是一个协程,它将在等待时将控件传递给事件循环。