我是Python和函数式编程的新手。我使用的是2.7.6版本
我使用Tornado框架来发出异步网络请求。根据我对函数式编程的了解,我希望我的数据通过使用生成器来传输我的代码。我使用生成器完成了我需要的大部分工作,并在通过函数调用流转换数据时进行了转换。
在我的流的最后,我想要为某些数据发出REST请求。在我将数据提交给Tornado之前,我有一个for-loop,启动pull,然后发送http请求。 Tornado提供的http对象将回调函数作为一个选项,并且总是返回一个Future - 它实际上是一个Tornado Future对象,而不是官方的Python Future。
我的问题是,由于我现在使用生成器通过我的代码提取数据,我不再想使用回调函数。我的理由是,在从回调中获取数据之后,我的数据现在被推送到我的代码中,我再也无法使用生成器了。
我的目标是创建一个如下所示的界面:
urls = (...generated urls...)
responses = fetch(urls)
响应是完成的网址上的生成器。
我尝试做的事情 - 在许多方面 - 是将回调的结果转换为生成器。我正在考虑这样的事情,尽管我很快就会解决其他问题。但是,我希望我的fetch函数看起来像这样:
def fetch(urls):
def url_generator():
while True:
val = yield
yield val
@curry
def handler(gen, response):
gen.send(response)
gen = url_generator()
for u in urls:
http.fetch(u, callback=handler(gen))
return gen
我简化了代码和语法以专注于问题,但我认为这样可以正常工作。我的策略是定义一个协程/生成器,然后我会在收到它们时发送响应。
我最麻烦的是协程/发生器。即使我以上述方式定义一个生成器并执行以下操作,我也会得到一个无限循环 - 这是我的主要问题之一。
def gen():
while True:
val = yield
print 'val', val
yield val
print 'after', val
break
g = gen()
g.send(None)
g.send(10)
for e in g:
print e
这会在协程中按照预期打印val 10 after 10
,但for循环永远不会得到10的值。当中断时,它不会打印任何东西。如果我删除了中断,那么我得到无限循环:
val None
None
after None
None
val None
None
after None
None
...
如果我删除了for循环,那么协程只会在等待第二次产量时打印val 10
。我期待这个。但是,使用它并不能产生任何东西。
类似地,如果我删除for循环并用print next(g)
替换它,那么我得到一个StopIteration错误,我假设这意味着我在没有更多值的生成器上调用了下一个。
Anywho,当我深入研究Python时,我完全失去了。我认为这是Python中常见的情况,有人知道一个很好的方法。我搜索了将回调转换为生成器'等等,但没有多少运气。
另一方面,我可能会从http请求中获得每个未来,但我没有多少运气和#34;等待"关于未来收益率的完成情况。我阅读了很多关于'来自',但它似乎是Python 3特定的,而Tornado似乎还没有在Python 3上工作。
感谢您查看,感谢您提供的任何帮助。
答案 0 :(得分:3)
Tornado在Python 3上运行良好。
上面简化代码的问题在于,这不符合您的期望:
val = yield
你希望生成器在那里暂停(阻止你的for循环),直到其他一些函数调用g.send(value)
,但事实并非如此。相反,代码的行为如下:
val = yield None
因此for循环接收None
值的速度与处理它们的速度一样快。收到每个None
后,它会隐式调用g.next()
,这与g.send(None)
相同。所以,你的代码等同于:
def gen():
while True:
val = yield None
print 'val', val
yield val
print 'after', val
g = gen()
g.send(None)
g.send(10)
while True:
try:
e = g.send(None)
print e
except StopIteration:
break
阅读此版本的代码,其中隐式行为是明确的,我希望很清楚为什么它只是在无限循环中生成None
。
你需要的是一个函数将一个函数添加到队列头部的方法,而另一个函数阻止等待项目,并在它们准备好时将它们拉出队列的尾部。从Tornado 4.2开始,我们就是这样:
http://www.tornadoweb.org/en/stable/queues.html
网络蜘蛛示例接近您想要做的事情,我相信您可以适应它: