在iPython中运行扭曲的反应堆

时间:2016-10-03 15:17:16

标签: python ipython twisted

我知道这通常是用twistd完成的,但是我想用iPython来测试扭曲代码上的'live'代码。

How to start twisted's reactor from ipython基本上问了同样的事情,但第一个解决方案不再适用于当前的ipython / twisted,而第二个解决方案也无法使用(线程会引发多个错误)。

https://gist.github.com/kived/8721434有一个名为TPython的东西,它声称可以做到这一点,但运行它似乎工作,除了客户端永远不会连接到服务器(运行相同的客户端在python shell中工作)。

使用Conch Manhole,还是有办法让iPython玩得很好(可能是_threadedselect)。

供参考,我要求使用ipython 5.0.0,python 2.7.12,twisted 16.4.1

2 个答案:

答案 0 :(得分:1)

在实时解释器中运行异步代码通常很麻烦。最好只在后台运行异步脚本,并在单独的解释器中执行iPython内容。您可以使用文件或TCP进行相互通信。如果这超过你的头脑,那是因为它并不总是很简单,最好避免可能的麻烦。

但是,您会很高兴知道在非异步应用程序中使用Twisted有一个名为crochet的强大项目。它确实是我最喜欢的模块之一,我感到震惊的是它没有被广泛使用(你可以改变它; D虽然)。 crochet模块有一个run_in_reactor装饰器,它在由crochet本身管理的单独线程中运行Twisted反应器。这是一个快速类示例,它执行对Star Wars RESTFul API的请求,然后将JSON响应存储在列表中。

from __future__ import print_function
import json

from twisted.internet import defer, task
from twisted.web.client import getPage

from crochet import run_in_reactor, setup as setup_crochet
setup_crochet()

class StarWarsPeople(object):
    people_id = [_id for _id in range(1, 89)]
    people = []

    @run_in_reactor
    def requestPeople(self):
        """
        Request Star Wars JSON data from the SWAPI site.
        This occurs in a Twisted reactor in a separate thread.
        """
        for _id in self.people_id:
            url = 'http://swapi.co/api/people/{0}'.format(_id).encode('utf-8')
            d = getPage(url)
            d.addCallback(self.appendJSON)

    def appendJSON(self, response):
        """
        A callback which will take the response from the getPage() request, 
        convert it to JSON, then append it to self.people, which can be 
        accessed outside of the crochet thread.
        """
        response_json = json.loads(response.decode('utf-8'))
        #print(response_json)    # uncomment if you want to see output
        self.people.append(response_json)

将其保存在文件中(例如:swapi.py),打开iPython,导入新创建的模块,然后像这样运行快速测试:

from swapi import StarWarsPeople
testing = StarWarsPeople()
testing.requestPeople()

from time import sleep
for x in range(5):
    print(len(testing.people))
    sleep(2)

正如您所看到的,它在后台运行,并且主线程中仍然可以发生内容。您可以像往常一样继续使用iPython解释器。你甚至可以在后台运行一个沙井来进行一些很酷的黑客攻击!

参考

答案 1 :(得分:0)

虽然这不能回答我认为的问题,但它确实回答了我发布的问题。嵌入ipython的工作原理是您可以在反应堆运行时访问业务对象。

from twisted.internet import reactor
from twisted.internet.endpoints import serverFromString
from myfactory import MyFactory

class MyClass(object):
    def __init__(self, **kwargs):
        super(MyClass, self).__init__(**kwargs)
        server = serverFromString(reactor, 'tcp:12345')
        server.list(MyFactory(self))
        def interact():
            import IPython
            IPython.embed()
        reactor.callInThread(interact)

if __name__ == "__main__":
    myclass = MyClass()
    reactor.run()

使用python myclass.py或类似内容调用上述内容。