取消在单独线程中的 Python open()。

huangapple go评论120阅读模式
英文:

Cancel python open() in separate thread

问题

我的目标是异步地打开一个命名管道。不幸的是,该管道会阻塞,直到另一端也打开为止。因此,为了防止我的应用程序阻塞,我在一个单独的线程中执行此调用。问题是,我没有办法取消这个线程。

如果运行此脚本,应该会看到打印出"Hello World"。如果您尝试通过类似以下方式连接到脚本:`echo "Hello" > /path/to/pipe`,它应该会在控制台上打印出"Connected to <pipe>"。如果您尝试退出,程序会按预期关闭。但是,如果您不连接到管道并尝试退出,程序将挂起,因为它无法取消运行中的线程。

这个问题类似于这个问题:https://stackoverflow.com/questions/71416383/python-asyncio-cancelling-a-to-thread-task-wont-stop-the-thread
在这种情况下,建议使用线程事件(threading.Event)。但在我的情况下,这不会起作用,因为我执行了一个单一的阻塞调用。我可以做什么?
英文:

My goal is to open a named pipe asynchronously. Unfortunately the pipe blocks until it is also opened from the other side. Thus, to prevent my application from blocking I am performing this call in a separate thread. The problem is, that I have no way of cancelling this thread.

import asyncio
import signal

async def connect_pipe(pipe):
    print(f&quot;Connecting to {pipe}&quot;)
    loop = asyncio.get_event_loop()
    try:
        pipe = await asyncio.to_thread(open, pipe, &quot;rb&quot;, 0)
        print(f&quot;Connected to {pipe}&quot;)
    except asyncio.CancelledError:
        print(f&quot;Connecting to {pipe} was interrupted&quot;)


def exit_handler():
    task.cancel()
    loop.stop()


loop = asyncio.get_event_loop()
loop.add_signal_handler(signal.SIGINT, exit_handler)
task = loop.create_task(connect_pipe(&quot;/path/to/pipe&quot;))
print(&quot;Hello World&quot;)
loop.run_forever()
loop.close()

If you run this script you should see Hello World printed. If you connect to the script by doing something like: echo &quot;Hello&quot; &gt; /path/to/pipe it should print Connected to <pipe> to the console. If you try to exit, the program closes as expected. However, if you don't connect to the pipe and try to exit, the program will hang because it can't cancel the running thread.

The question is similar to this one: https://stackoverflow.com/questions/71416383/python-asyncio-cancelling-a-to-thread-task-wont-stop-the-thread
In this case the use of threading.Event is suggested. But this won't work in my case since I am performing a single blocking call. What can I do?

答案1

得分: 1

我认为我已经找到了解决方案。关键是使用 os.open(pipe, os.O_RDONLY | os.O_NONBLOCK) 这将返回一个文件描述符,可以使用 os.fdopen 打开。如果您想向管道写入,可以使用 os.open(pipe, os.O_WRONLY | os.O_NONBLOCK) 这将在管道未连接到读取器时引发异常。对于其他遇到相同问题的人,这可能会有所帮助:https://stackoverflow.com/questions/34754397/can-i-open-a-named-pipe-on-linux-for-non-blocked-writing-in-python

英文:

I think I have found the solution. The key is to use os.open(pipe, os.O_RDONLY | os.O_NONBLOCK) This will return a file descriptor which can be opened using os.fdopen. In case you want to write to a pipe you do os.open(pipe, os.O_WRONLY | os.O_NONBLOCK) This will throw an exception if the pipe is not connected to a reader. For other people with the same problem, this might be helpful: https://stackoverflow.com/questions/34754397/can-i-open-a-named-pipe-on-linux-for-non-blocked-writing-in-python

huangapple
  • 本文由 发表于 2023年6月25日 23:27:17
  • 转载请务必保留本文链接:https://go.coder-hub.com/76551138.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定