yield from我怀疑这与 b/w &的差异有关await。然而,除了新对象被指定为 an 之外async_generator,我还不清楚它和 a 之间的差异的后果coroutine。(除了我在标题中提出的问题之外,我不知道还能如何问这个问题......)
import asyncio
async def async_generator_spits_out_letters():
yield 'a'
yield 'b'
yield 'c'
yield 'd'
await asyncio.sleep(0)
async def coroutine_prints_messages():
while True:
print('hi')
await asyncio.sleep(2)
def test_it():
print(type(async_generator_spits_out_letters))
print(type(coroutine_prints_messages))
# This is how I choose to do newlines....it's easier for me to read. :[
print(); print()
print(type(async_generator_spits_out_letters()))
print(type(coroutine_prints_messages()))
Run Code Online (Sandbox Code Playgroud)
这给出:
<class 'async_generator'>
<class 'coroutine'>
<class 'function'>
<class 'function'>
Run Code Online (Sandbox Code Playgroud)
我无法理解这一点......
kotlin 中协程的想法是抽象挂起和回调的概念并编写简单的顺序代码。与线程类似,您永远不需要担心协程是否被挂起。
suspendCoroutineOrReturn它们的目的是什么?COROUTINE_SUSPENDED在什么情况下您会使用它们?
我正在尝试使用 Kotlin 协程在后台运行一些繁重的工作。
但我收到此错误消息,
“android.view.ViewRootImpl$CalledFromWrongThreadException:只有创建视图层次结构的原始线程才能触摸其视图。”
fun setList() {
media_image_list.adapter = imageListAdapter
...
launch {
val images = getImages(galleryPath)
imageListAdapter.setItems(images)
}
}
suspend private fun getImages(): MutableList<Image> {
val uri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI
...
}
Run Code Online (Sandbox Code Playgroud)
如何让它在后台正确运行?
覆盖方法 on_finish()。装饰此方法.gen.coroutine以使其异步,它起作用了。
@gen.coroutine
def on_finish(self):
print("==========on_finish==============")
Run Code Online (Sandbox Code Playgroud)
但使用async def使其异步,它失败了。
async def on_finish(self):
print("==========on_finish==============")
# RuntimeWarning: coroutine 'BaseHandler.on_finish' was never awaited
Run Code Online (Sandbox Code Playgroud)
self.on_finish()
为什么我不能async def用来使它异步?
我正在使用PyMemoize库来缓存协程。我装饰了协程,但是当 Python 调用它时,我得到:
TypeError: can't pickle coroutine objects
Run Code Online (Sandbox Code Playgroud)
发生这种情况是因为PyMemoize内部尝试腌制协程并将其存储在 Redis 中。为此,它使用shelve.Shelf,而后者又使用pickle. 问题是,由于未知的原因,pickle不支持 pickling 协程。
我尝试用它来腌制协程dill并且它有效。我如何知道shelve用作dill序列化后端?
我尝试过猴子补丁shelve,但没有成功(我不知道为什么):
TypeError: can't pickle coroutine objects
Run Code Online (Sandbox Code Playgroud) 我正在处理一个 http 库(特别是用于进行 graphql 调用的库),它的 API 仅提供阻塞调用,并且是用 Java 编写的。
现在,我正在使用 Kotlin 并使用协程库编写应用程序,这让我想知道应该如何使用协程进行阻塞网络调用。
所以我得到了这段代码:
class DataService(val client: Client) {
suspend fun getData(request: Request) {
// process request
client.makeServiceCall(...)
//deal with response
}
}
class Client() {
suspend fun makeServiceCall(...) {
library.query(....) //make a network call using the above mentioned library
}
}
Run Code Online (Sandbox Code Playgroud)
所以我想知道是否Client.makeServiceCall()应该实际标记为挂起函数,因为它实际上并不挂起,它仅在进行网络调用时才阻塞。DataService.getData()我应该如何从到进行调用makeServiceCall()并仍然遵守结构化并发原则(例如父子协程关系)?
我有一些协程:
IEnumerator a(){ /* code */ }
IEnumerator b(){ /* code */ }
IEnumerator c(){ /* code */ }
Run Code Online (Sandbox Code Playgroud)
我想创建一个协程,该协程调用a,b并c并行但在继续之前等待所有这些完成,例如:
IEnumerator d(){
StartCoroutine(a());
StartCoroutine(b());
StartCoroutine(c());
wait until all of them are over
print("all over");
}
Run Code Online (Sandbox Code Playgroud)
显然我可以为每个协程使用一个布尔值来保存其当前状态,但由于这种方法不可扩展,我更喜欢更直接的解决方案。
C++20 引入了协程,可以用来创建生成器和其他类似的东西:
generator<int> counter(int max) {
for(int i = 0; i < max; i++) {
co_yield i;
}
}
Run Code Online (Sandbox Code Playgroud)
有什么方法可以创建一个协程,以便调用者可以提供一个响应,该响应co_yield在协程恢复后返回?让我们称其为 achannel而不是生成器。
这是我希望能够做的一个例子:
channel<int, int> accumulator(int initial) {
while(true) {
// Can channel be written so co_yield provides a response?
int response = co_yield initial;
initial += response;
}
}
Run Code Online (Sandbox Code Playgroud)
在这里,每当调用者恢复协程时,它都会提供一个值,co_yield一旦协程恢复,该值就会返回,如下所示:
std::vector<int> accumulate(std::vector<int> values) {
channel<int, int> acc = accumulator(0);
std::vector<int> summed_values;
for(int v : values) {
// Get whatever value was yielded by the …Run Code Online (Sandbox Code Playgroud) 所以通常当你不得不进行不同的 API 调用并等待时,你会做这样的事情:
viewModelScope.launch {
withContext(dispatcherProvider.heavyTasks) {
val apiResponse1 = api.get1() //suspend function
val apiResponse2 = api.get2() //suspend function
if (apiResponse1.isSuccessful() && apiResponse2.isSuccessful() { .. }
}
}
Run Code Online (Sandbox Code Playgroud)
但是如果我必须使用不同的参数同时执行多个相同的 API 调用,会发生什么:
viewModelScope.launch {
withContext(dispatcherProvider.heavyTasks) {
val multipleIds = listOf(1, 2, 3, 4, 5, ..)
val content = arrayListOf<CustomObj>()
multipleIds.forEach { id ->
val apiResponse1 = api.get1(id) //suspend function
if (apiResponse1.isSuccessful()) {
content.find { it.id == id }.enable = true
}
}
liveData.postValue(content)
}
}
Run Code Online (Sandbox Code Playgroud)
第二种方法的问题是它将遍历multipleIds列表的所有 id并进行异步调用,但content可能会在此之前发布。如何等待每个循环的所有响应完成,然后 …
在有关 Context Vars 的 Python 文档中,描述了 Context::run 方法以启用在上下文中执行可调用对象的更改,以便可调用对象对上下文执行的更改包含在复制的上下文中。如果你需要执行协程怎么办?为了实现相同的行为,你应该怎么做?
就我而言,我想要的是这样的东西来处理可能嵌套事务的事务上下文:
my_ctxvar = ContextVar("my_ctxvar")
async def coro(func, transaction):
token = my_ctxvar.set(transaction)
r = await func()
my_ctxvar.reset(token) # no real need for this, but why not either
return r
async def foo():
ctx = copy_context()
# simplification to one case here: let's use the current transaction if there is one
if tx_owner := my_ctxvar not in ctx:
tx = await create_transaction()
else:
tx = my_ctxvar.get()
try:
r = await ctx.run(coro) # not …Run Code Online (Sandbox Code Playgroud) python coroutine async-await python-asyncio python-contextvars
coroutine ×10
kotlin ×3
python ×3
android ×2
asynchronous ×2
suspend ×2
async-await ×1
blocking ×1
c# ×1
c++ ×1
c++20 ×1
dill ×1
generator ×1
ienumerator ×1
jvm ×1
nonblocking ×1
pickle ×1
retrofit ×1
shelve ×1
tornado ×1