Асинхронный код в целом может быть проблематичным для запуска в реальном интерпретаторе. Лучше всего запустить скрипт async в фоновом режиме и сделать свой материал iPython в отдельном интерпретаторе. Вы можете взаимодействовать с файлами или TCP. Если это пошло по вашей голове, это потому, что это не всегда просто, и лучше всего избегать хлопот.
Тем не менее, вы будете рады узнать, что есть отличный проект под названием crochet
для использования Twisted в неасинхронных приложениях. Это действительно один из моих любимых модулей, и я шокирован тем, что он не используется более широко (вы можете это изменить, но это правда). В модуле crochet
есть декоратор run_in_reactor
, который запускает реактор Twisted в отдельном потоке, управляемом самим crochet
. Вот пример быстрого класса, который выполняет запросы к API RESTFul Star Wars, а затем сохраняет ответ 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, как обычно. У вас даже может быть люк, бегущий в фоновом режиме, для какого-то классного взлома!
Ссылки
Это в основном то, что я уже делаю в своем «реальном» приложении, запущенном в отдельном потоке из пользовательского интерфейса. Спасибо за ссылку на вязание крючком, но я всегда полагал, что она больше подходит для веб-WSGI, и где мне нужно эмулировать поведение блокировки. Теперь я пытаюсь выполнить inlineCallbacks/yield (что похоже на wait_for). –
Вязание крючком не только для веб-материалов. Вы не предоставили прецедента, поэтому я произвольно выбрал что-то, и выбор веб-запросов был выбран: D. Вероятно, я должен был привести пример 'wait_for'', но в то время, когда я не знал контекста вашей проблемы –
О, я не хотел подразумевать, что это было только для Интернета. Я понимаю это как наиболее полезное для вещей, которые ДОЛЖНЫ блокировать (wsgi, sqlalchemy), в отличие от живого интерпретатора, который уже асинхронен, чтобы начать с (или GUI-инструментарий, таких как киви, которые по своей сути связаны с фреймами) –