在python3.5中异步设置描述符
我可以写一个描述符,返回一个可以期待的未来在python3.5中异步设置描述符,python,python-3.5,python-asyncio,descriptor,Python,Python 3.5,Python Asyncio,Descriptor,我可以写一个描述符,返回一个可以期待的未来 class AsyncDescriptor: def __get__(self, obj, cls=None): # generate some async future here return future def __set__(self, obj, value): # generate some async future here return future
class AsyncDescriptor:
def __get__(self, obj, cls=None):
# generate some async future here
return future
def __set__(self, obj, value):
# generate some async future here
return future
class Device:
attr=AsyncDescriptor()
device=Device()
现在,我可以在与value=wait device.attr
的协同程序中获取值
如何设置此属性
->语法错误:无法分配给等待表达式等待设备。attr=5
->TypeError:object NoneType不能在'await'表达式中使用await setattr(设备'attr',5)
->运行时警告:从未等待协同路由“\uuuu set\uuuu”device.attr=5
\uuuuu get\uuuuu
返回未来可能是明智的,但Python 3.5根本不支持将\uuuuuu set\uuuuuuuu
异步。Python忽略了\uuuuu set\uuuuu
的返回值,因为没有赋值的“返回值”。对\uuuu set\uuuu
的调用始终是同步的。像a=(b.c=5)
这样的东西实际上会引发一个SyntaxError
如果允许像wait device.attr=5
这样的异步分配,则可能会有一个单独的异步描述符协议,即使用协程\uuuu aget\uuu
和\uu aset\uuuu
作为特殊方法,类似于异步上下文管理器(与/\uu aenter\uuu
异步)和异步迭代(async for
/\uuu aiter\uuuu
)。有关async
/wait
支持背后的设计决策,请参阅
还请注意,\uuuuuuu获取
返回未来不会使\uuuuu获取
成为一个协同程序
如果没有进一步的上下文,看起来您想在描述符协议提供的属性访问抽象背后隐藏一些东西,最好是显式地完成,但这当然取决于您。您试图做的事情是不可能的(使用Python 3.5)
虽然\uuuu get\uuuu
返回一个未来可能是明智的,但是Python 3.5不支持将\uuu set\uuuuuu
异步。Python忽略了\uu set\uuuuuu
的返回值,因为没有赋值的“返回值”。对\uu set\uuuuuu
的调用总是同步的。类似于a=(b.c=5)
实际上引发了一个SyntaxError
,正如您已经注意到的那样
如果允许像wait device.attr=5
这样的异步分配,则可能会有一个单独的异步描述符协议,即使用协程\uuuu aget\uuu
和\uu aset\uuuu
作为特殊方法,类似于异步上下文管理器(与/\uu aenter\uuu
异步)和异步迭代(async for
/\uuu aiter\uuuu
)。有关async
/wait
支持背后的设计决策,请参阅
还请注意,\uuuuuuu获取
返回未来不会使\uuuuu获取
成为一个协同程序
如果没有进一步的上下文,看起来您想在描述符协议提供的属性访问抽象背后隐藏一些东西,最好是显式地完成,但这当然取决于您。但是python非常好,如果您想编写device.attr=5,但等待设置
操作时,您只需借助上下文块即可(我不认为这是一个好主意,尽管它在无线程python场景中可能很有用):
import asyncio, sys
async def main():
obj.attr = "not async value"
print(obj.attr)
print()
print("now set with an async value")
async with aio(obj):
# ============== yes i can, thanks python ! ===
obj.attr = 5
# =============================================
print(obj.attr)
print("bye")
flush_io()
def flush_io():
sys.stdout.flush()
sys.stderr.flush()
class attr:
def __init__(self, value):
self.value = value
def __get__(self, obj, objtype):
if obj is None:
print("__get__", obj, objtype)
return self
print("get", obj, objtype)
return self.value
def __set__(self, obj, value):
if value is not obj.__class__:
if obj in aio.updating:
aio.setlist.append([self, value])
print(" future set", self, value)
return
self.value = value
print("set", obj, value)
return
print("__set__", obj, value)
async def setter(self, value):
print(" async updating", self, end=" ")
for i in range(value):
await asyncio.sleep(1)
print(".", end="")
flush_io()
print()
self.value = value
def __repr__(self):
return "<async attr>"
class aobj:
attr = attr("empty")
def __repr__(self):
return "<aobj>"
class aio:
updating = []
setlist = []
def __call__(self, obj):
self.updating.append(obj)
return self
async def __aenter__(self):
print("aenter", self.updating)
async def __aexit__(self, *tb):
self.updating.pop()
while len(self.setlist):
obj, value = self.setlist.pop()
await obj.setter(value)
print("aexit")
aio = aio()
obj = aobj()
loop = asyncio.get_event_loop()
loop.run_until_complete(main())
导入异步IO,系统
异步def main():
obj.attr=“非异步值”
打印(对象属性)
打印()
打印(“现在设置为异步值”)
与aio(obj)异步:
#===============是的,我能,谢谢你===
obj.attr=5
# =============================================
打印(对象属性)
打印(“再见”)
刷新_io()
def flush_io():
sys.stdout.flush()
sys.stderr.flush()
类别属性:
定义初始值(自身,值):
自我价值=价值
定义获取(self、obj、objtype):
如果obj为无:
打印(“\uuuu get\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu
回归自我
打印(“获取”、对象、对象类型)
回归自我价值
定义设置(自身、对象、值):
如果值不是对象。\uuuu类\uuuuj:
如果目标在aio.update中:
aio.setlist.append([self,value])
打印(“未来设置”、自身、值)
返回
自我价值=价值
打印(“设置”、对象、值)
返回
打印(“\uuuuuuuuuuuuuuuuuuuuuu”,对象,值)
异步def设置器(自身,值):
打印(“异步更新”,self,end=”“)
对于范围内的i(值):
等待asyncio.sleep(1)
打印(“.”,end=“”)
刷新_io()
打印()
自我价值=价值
定义报告(自我):
返回“”
aobj类:
attr=attr(“空”)
定义报告(自我):
返回“”
aio类:
更新=[]
集合列表=[]
定义呼叫(自我,obj):
self.updateing.append(obj)
回归自我
异步定义(自):
打印(“aenter”,自我更新)
异步定义aexit(self,*tb):
self.updateing.pop()
而len(self.setlist):
obj,value=self.setlist.pop()
等待对象设置器(值)
打印(“aexit”)
aio=aio()
obj=aobj()
loop=asyncio.get\u event\u loop()
循环。运行\u直到完成(main())
但是python非常棒,所以如果您想编写device.attr=5,但等待设置
操作时,您只需借助上下文块即可(我不认为这是一个好主意,尽管它在无线程python场景中可能很有用):
import asyncio, sys
async def main():
obj.attr = "not async value"
print(obj.attr)
print()
print("now set with an async value")
async with aio(obj):
# ============== yes i can, thanks python ! ===
obj.attr = 5
# =============================================
print(obj.attr)
print("bye")
flush_io()
def flush_io():
sys.stdout.flush()
sys.stderr.flush()
class attr:
def __init__(self, value):
self.value = value
def __get__(self, obj, objtype):
if obj is None:
print("__get__", obj, objtype)
return self
print("get", obj, objtype)
return self.value
def __set__(self, obj, value):
if value is not obj.__class__:
if obj in aio.updating:
aio.setlist.append([self, value])
print(" future set", self, value)
return
self.value = value
print("set", obj, value)
return
print("__set__", obj, value)
async def setter(self, value):
print(" async updating", self, end=" ")
for i in range(value):
await asyncio.sleep(1)
print(".", end="")
flush_io()
print()
self.value = value
def __repr__(self):
return "<async attr>"
class aobj:
attr = attr("empty")
def __repr__(self):
return "<aobj>"
class aio:
updating = []
setlist = []
def __call__(self, obj):
self.updating.append(obj)
return self
async def __aenter__(self):
print("aenter", self.updating)
async def __aexit__(self, *tb):
self.updating.pop()
while len(self.setlist):
obj, value = self.setlist.pop()
await obj.setter(value)
print("aexit")
aio = aio()
obj = aobj()
loop = asyncio.get_event_loop()
loop.run_until_complete(main())
导入异步IO,系统
异步def main():
obj.attr=“非异步值”
打印(对象属性)
打印()
打印(“现在设置为异步值”)
与aio(obj)异步:
#===============是的,我能,谢谢你===
obj.attr=5
# =============================================
打印(对象属性)
打印(“再见”)
刷新_io()
def flush_io():
sys.stdout.flush()
sys.stderr.flush()
C