1

I'm using Python 3.4.3. While my event loop is working, I'm communicating with some infinite process (tail -f in the example). Once all other tasks are done, I cancel tail task as well, wait for it to finish and close the loop.

import asyncio
import time

@asyncio.coroutine
def tailf():
    try:
        create = asyncio.create_subprocess_exec(
            'tail', '-f', '/tmp/file',
            stdout=asyncio.subprocess.PIPE,
        )
        proc = yield from create

        while True:
            l = yield from proc.stdout.readline()
            print(l)

    except BaseException as e:
        print('CAUGHT', type(e))


@asyncio.coroutine
def task():
    yield from asyncio.sleep(1)

loop = asyncio.get_event_loop()
tailf_task = loop.create_task(tailf())
loop.run_until_complete(asyncio.wait([task()]))
tailf_task.cancel()
loop.run_until_complete(asyncio.wait([tailf_task]))
loop.close()

The output is:

b'123\n'
CAUGHT <class 'concurrent.futures._base.CancelledError'>
Exception ignored in: Exception ignored in:

Do echo 123 > /tmp/file to get the same result before running the example.

It all works as expected except I got that warning at the end of the script.

I believe the reason is yield from proc.stdout.readline() being interrupted, but I would like to catch the exception in that case.

So, the question is: what am I doing wrong?

And the more broad one: how do I debug such warning next time?

3
  • If you change it to except BaseException as e:, does that catch it? Commented Apr 11, 2018 at 16:08
  • Thanks for the idea, fixed. The warning is still there though. Commented Apr 11, 2018 at 16:13
  • It was just a guess that canceling a coro written as a generator (pre-3.5 style) might raise a GeneratorExit, which is not meant to be caught with except Exception, only BaseException. But I guess that's not it. Commented Apr 11, 2018 at 16:15

1 Answer 1

1

Once the coroutine that communicates with tail -f is canceled, it should terminate the process and wait for it to end (look at the except):

@asyncio.coroutine
def tailf():
    try:
        create = asyncio.create_subprocess_exec(
            'tail', '-f', '/tmp/file',
            stdout=asyncio.subprocess.PIPE,
        )
        proc = yield from create

        while True:
            l = yield from proc.stdout.readline()
            print(l)
    except asyncio.CancelledError:
        proc.terminate()
        yield from proc.wait()

You don't get the warning in Python 3.6, but you still get unterminated tail -f hanging in the process list.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.