I have this function:
我有这个功能:
def check_for_throttling(r):
if r.status_code == responses.THROTTLING:
#<lots of other stuff>
time.sleep(Throttle.DELAY)
Throttle.DELAY = Throttle.DELAY + 2
return r
I also have this async coroutine:
我还有一个异步协同例程:
async def check_for_throttling(r):
if r.status_code == responses.THROTTLING:
#<lots of other stuff>
await async.sleep(Throttle.DELAY)
Throttle.DELAY = Throttle.DELAY + 2
return r
My question - is there a way to use one block of code for both scenarios?
我的问题是,有没有办法在两种情况下都使用一块代码?
I have other situations that have more complex logic than the example.
我还有比这个例子更复杂的逻辑的其他情况。
And all those situations, I have a function and an async coroutine that are identical except that one has time.sleep()
and the other uses async.sleep()
在所有这些情况下,我有一个函数和一个异步协同例程,它们都是相同的,只是其中一个有时间。睡眠(),另一个使用异步睡眠()
Thank you!
谢谢!
更多回答
I don’t understand why can’t you make a function do_if_throttled
and call it from the code above?
我不明白为什么不能让一个函数do_if_throtted并从上面的代码中调用它?
time.sleep
rather breaks the concept of an event loop, so perhaps find a way to delete that one all together. I found switching from requests
to aiohttp
helped, assuming this is what you are doing.
时间。睡眠打破了事件循环的概念,所以也许可以找到一种方法把它一起删除。我发现从请求转换到aiohttp很有帮助,假设这就是您正在做的。
If #<lots of other stuff>
is identical in the two cases, then it means its not doing any blocking activity. You could pull that code out and keep these two wrappers for the different ways to do things.
如果#<许多其他东西>在这两种情况下是相同的,那么它意味着它没有做任何阻塞活动。您可以取出该代码,并保留这两个包装器,以用于不同的操作方式。
The "obvious thing to do" there is to write the asyncio version of your code, and, if you have a sync thread or sync-block, to have a created loop on that thread, and call loop.run_until_complete(async_check_for_throtling())
on that code.
“显而易见的事情”是编写代码的异步版本,如果您有同步线程或同步块,则在该线程上创建一个循环,并对该代码调用loop.run_until_complete(async_check_for_throtling())。
If you are on a thread that is not using an asyncio loop for nothing else, as long as you keep a loop around "idle" doing this is not different from doing a synchronous call.
如果您所在的线程不会因为其他原因而使用异步循环,那么只要您让一个循环处于“空闲”状态,这样做与进行同步调用没有什么不同。
It is otherwise complicated to have code that can be called in both sync and async ways, because async code must return immediately an awaitable object when called. And simply writing the "await" keyword inside a function makes it automatically an async function - so there is no way to have an "if" that will take either code path.
在其他方面,拥有既可以以同步方式调用又可以以异步方式调用的代码是复杂的,因为当调用异步代码时,必须立即返回可等待的对象。只需在函数中写入“await”关键字,它就会自动成为一个异步函数--所以不可能有一个“if”来接受任何一个代码路径。
but if one insists
但如果有人坚持
Even writing it as a class whose instances would have the common code in certain methods, and the async-code and sync code separated in others, will have several limitations on the form that can take - but it can be done:
即使将它编写为一个类,其实例在某些方法中具有公共代码,而在其他方法中分离异步代码和同步代码,对于可以采用的形式也会有几个限制-但它是可以做到的:
class CheckTrottling:
def core(self, r):
if r.status_code == responses.THROTTLING:
#<lots of other stuff>
yield
Throttle.DELAY = Throttle.DELAY + 2
return r
async def async_check(self, r):
runner = self.core(r)
next(runner)
await asyncio.sleep(...)
try:
next(runner)
except StopIteration as stop:
value = stop.value
return value
def check(self, r):
runner = self.core(r)
next(runner)
time.sleep(...)
try:
next(runner)
except StopIteration as stop:
value = stop.value
return value
You then instantiate the class (it can be a single, module level instance), you can call either the async_check or check method as desired.
然后实例化类(它可以是单个模块级别的实例),您可以根据需要调用async_check或check方法。
In this model the main function will "pause" at the yield expression, and be resumed on a following next
call - so it can be driven by an external function which can then be sync or async, and do whatever mode of "sleep" it prefers.
在此模型中,主函数将在YILD表达式处“暂停”,并在下一次调用时恢复--因此它可以由外部函数驱动,然后该外部函数可以是同步或异步的,并且可以执行它喜欢的任何“休眠”模式。
However, as it can be seen, this is essentialy replicating the very logic of asyncio to start with. (Back in Python 3.4, the first version of asyncio would use "yield", as the keywords for async code were not in the language yet). It is easy to perceive them that my first recommendation above, of writing the common code as async in the first place, should e the preferred way to go.
然而,正如可以看到的那样,这本质上是复制了Ayncio的逻辑。(回到Python3.4,Asyncio的第一个版本将使用“Year”,因为Async代码的关键字还不在该语言中)。很容易感觉到,我上面的第一个建议,即首先将公共代码作为异步编写,应该是首选的方法。
更多回答
我是一名优秀的程序员,十分优秀!