You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Asyncio报错:Task got bad yield?udiskie代码运行故障求助

问题排查:udiskie异步代码抛出RuntimeError错误

问题描述

以下代码尝试通过udiskie异步卸载设备,但运行时抛出异常:

import asyncio
import udiskie
import udiskie.config
import udiskie.udisks2

async def main():
    device = '/dev/mmcblk0p1'
    config = udiskie.config.Config.from_file()
    udisks = await udiskie.udisks2.Daemon.create()
    await udisks.connect()
    try:
        await udisks.unmount(device)
    finally:
        await udisks.disconnect()

if __name__ == '__main__':
    asyncio.run(main())

报错信息:

test.py", line 9, in main
    udisks = await udiskie.udisks2.Daemon.create()
  File "/usr/lib/python3/dist-packages/udiskie/udisks2.py", line 699, in create
    proxy = await dbus.connect_service(*service)
  File "/usr/lib/python3/dist-packages/udiskie/dbus.py", line 288, in connect_service
    proxy = await proxy_new_for_bus(
  File "/usr/lib/python3/dist-packages/udiskie/dbus.py", line 279, in proxy_new_for_bus
    result = await future
  File "/usr/lib/python3/dist-packages/udiskie/async_.py", line 92, in __await__
    return (yield self)
RuntimeError: Task got bad yield: <udiskie.async_.Future object at 0x7fbb12c100>

错误原因

核心问题是udiskie自定义的udiskie.async_.Future类与标准库asyncio的Task机制不兼容。udiskie的Future在__await__方法中直接yield self,而asyncio的Task仅支持yield符合标准协议的可等待对象(如asyncio原生Future、Task或协程对象),无法处理这种自定义的yield逻辑。该问题多出现于udiskie版本较旧、异步实现未完全适配asyncio规范的场景。

解决方法

方法1:使用udiskie自带事件循环运行代码

udiskie提供了适配自身异步逻辑的事件循环,替换asyncio.run()即可:

import udiskie
import udiskie.config
import udiskie.udisks2
from udiskie.async_ import run

async def main():
    device = '/dev/mmcblk0p1'
    config = udiskie.config.Config.from_file()
    udisks = await udiskie.udisks2.Daemon.create()
    await udisks.connect()
    try:
        await udisks.unmount(device)
    finally:
        await udisks.disconnect()

if __name__ == '__main__':
    run(main())

方法2:升级udiskie到最新版本

新版本udiskie大概率修复了异步兼容问题,执行升级命令:

# pip安装的版本
pip install --upgrade udiskie

# Debian/Ubuntu系统包管理安装的版本
sudo apt install --only-upgrade python3-udiskie

方法3:改用udiskie同步API

若无需异步逻辑,直接使用同步方式操作:

import udiskie
import udiskie.config
import udiskie.udisks2

def main():
    device = '/dev/mmcblk0p1'
    config = udiskie.config.Config.from_file()
    udisks = udiskie.udisks2.Daemon()
    udisks.connect()
    try:
        udisks.unmount(device)
    finally:
        udisks.disconnect()

if __name__ == '__main__':
    main()

方法4:手动适配udiskie Future到asyncio

若必须依赖asyncio事件循环,可将udiskie自定义Future包装为asyncio兼容对象:

import asyncio
import udiskie
import udiskie.config
import udiskie.udisks2
from udiskie.async_ import Future as UdiskieFuture

def udiskie_future_to_asyncio(fut: UdiskieFuture):
    loop = asyncio.get_event_loop()
    asyncio_fut = loop.create_future()
    def on_done(_):
        try:
            result = fut.result()
            asyncio_fut.set_result(result)
        except Exception as e:
            asyncio_fut.set_exception(e)
    fut.add_done_callback(on_done)
    return asyncio_fut

async def main():
    device = '/dev/mmcblk0p1'
    config = udiskie.config.Config.from_file()
    # 手动处理每个udiskie Future
    daemon_fut = udiskie.udisks2.Daemon.create()
    udisks = await udiskie_future_to_asyncio(daemon_fut)
    
    connect_fut = udisks.connect()
    await udiskie_future_to_asyncio(connect_fut)
    
    try:
        unmount_fut = udisks.unmount(device)
        await udiskie_future_to_asyncio(unmount_fut)
    finally:
        disconnect_fut = udisks.disconnect()
        await udiskie_future_to_asyncio(disconnect_fut)

if __name__ == '__main__':
    asyncio.run(main())

内容的提问来源于stack exchange,提问作者Daniel

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.26 03:42:38