想象一下以下非常常见的情况:您编写了一个冗长而复杂的函数,并意识到应该将一些代码提取到一个单独的函数中以便重用和/或可读.通常,这个额外的函数调用不会改变程序的语义.
但是,现在假设您的函数是一个协程,并且您要提取的代码包含至少一个异步调用.将它提取到一个单独的函数现在突然改变你的程序语义,方法是插入一个新的协同程序产生的点,事件循环控制,并且可以在其间安排任何其他协程.
以前的例子:
async def complicated_func():
foo()
bar()
await baz()
Run Code Online (Sandbox Code Playgroud)
示例之后:
async def complicated_func():
foo()
await extracted_func()
async def extracted_func():
bar()
await baz()
Run Code Online (Sandbox Code Playgroud)
在之前的示例中,complicated_func保证不会在呼叫foo()和呼叫之间暂停bar().重构后,此保证将丢失.
我的问题是:是否有可能调用extracted_func()它立即执行,好像它的代码是内联的?或者是否有其他方法可以在不更改程序语义的情况下执行此类常见的重构任务?
我正在使用 Python 和 Click 编写一个 CLI 工具。其中一个命令有一个选项,其type=(str, str))使用方式如下:command subcommand --option foo bar。
第一个参数 (foo) 有多个选项可供选择,对于第一个参数的每个选择,第二个参数 (bar) 也有多个选项可供选择。因此第二个参数的选项取决于第一个参数的选择!
问题是:如何使用Click提供的支持来为此编写自动完成功能?
尤其:
下面的最小程序重现此问题。
import asyncio
import signal
class A:
def __init__(self):
self._event_loop = asyncio.new_event_loop()
def run(self):
print('starting event loop')
self._event_loop.run_forever()
print('event loop has stopped')
def stop(self):
print('stopping event loop')
self._event_loop.stop()
if __name__ == '__main__':
a = A()
def handle_term(*args):
a.stop()
signal.signal(signal.SIGTERM, handle_term)
a.run()
Run Code Online (Sandbox Code Playgroud)
如果运行程序并将SIGTERM发送给该进程,则将调用第16行中的print语句(停止事件循环),但程序不会终止,并且永远不会调用第13行中的print语句(事件循环已停止)。因此,似乎事件循环永远不会停止并且self._event_loop.run_forever()无限期地阻塞。
为什么是这样?
注意:程序的修改版本a.stop()可以按预期工作,而不是由信号处理程序调用,而是由具有延迟的单独线程调用。如何能有所作为怎么a.stop()叫?
我使用python-3.2.3 64bit,我看到一些奇怪的行为.
例如,使用解释器时:输入
>>> range(10)
Run Code Online (Sandbox Code Playgroud)
结果输出
range(0, 10)
Run Code Online (Sandbox Code Playgroud)
什么时候打印
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
Run Code Online (Sandbox Code Playgroud)
Simmilary输入
>>> l = range(10)
>>> f = filter( lambda x: x<2, l)
>>> f
Run Code Online (Sandbox Code Playgroud)
导致输出
<filter object at 0x00000000033481D0>
Run Code Online (Sandbox Code Playgroud)
但它应该是
[0, 1]
Run Code Online (Sandbox Code Playgroud)
显然,我无法对该对象做任何事情:
>>>> len(f)
Traceback (most recent call last):
File "<pyshell#5>", line 1, in <module>
len(f)
TypeError: object of type 'filter' has no len()
Run Code Online (Sandbox Code Playgroud)
这里有什么不对?
我想要一个在应用程序的生命周期内打开(输入?)的上下文管理器。它应该在模块加载时打开,并在模块销毁时关闭。
包装整个模块代码是行不通的,因为当模块加载完成时,上下文管理器将关闭,而当实际调用方法时,上下文管理器将不再打开。
import aiohttp
with context as c:
def f1():
c.do_something('one')
def f2():
c.do_something('two')
Run Code Online (Sandbox Code Playgroud)
具体来说,我想aiohttp.ClientSession为该模块创建一个,该模块可重用于多个不同的请求,并在应用程序停止时干净地关闭。为此使用上下文管理器是一个好主意还是有更好的方法?