Я отвечу на ваши вопросы (и утверждения, которые кажутся запутанными) один за другим:
"Примеры, которые не являются полными"
Повторение того, что я опубликовал в комментариях: см.два моих предыдущих ответа на полные примеры (https://stackoverflow.com/a/30399317/3334178 & https://stackoverflow.com/a/23274411/3334178) и прохождение Twisted Введение Крондо
Вы сказали, что вы обесцениваете их, потому что "Примерысетевой код в витой, который имеет встроенную и скрытую асинхронность ".Я не согласен с этим утверждением и объясню это в следующем разделе.
«Примеры не являются асинхронными»
Когда вы говорите об «асинхронном программировании», напрасно скручивая питоны / торнадо / асинцио(или Node.JS или C select / poll / kpoll) вы говорите о модели / шаблоне программирования, который позволяет программисту формировать свой код так, чтобы его части могли работать, в то время как другие части были заблокированы (почти во всехслучаи, когда блокировка вызвана тем, что часть программы вынуждена ждать ввода-вывода).
Эти библиотеки / языки, несомненно, будут иметь способы выполнения потоков и / или многопроцессорной обработки, но это слои, привитые поверхАсинхронный дизайн - и если это действительно то, что вам нужно (т.е. у вас есть исключительно связанные с процессором потребности), асинхронные системы будут плохим выбором.
Давайте использовать ваш «скрытый» комментарий, чтобы войти в этонемного больше
"Примеры сети - асыч, но асинхронность встроена и скрыта"
TФундаментальный элемент асинхронного дизайна заключается в том, что вы пишете свой код, чтобы он никогда не блокировался для ввода-вывода - вы вызывали сеть , но на самом деле мы говорим о сети / диске / клавиатуре / мыши / звуке /serial - все, что (по какой-либо причине) может работать медленнее, чем процессор ( и что в ОС есть дескриптор файла для ).
Кроме того, ничего «скрытого» не существуетпрочь "о том, как он функционирует - асинхронное программирование всегда использует неблокирующие (проверка состояния / обратные вызовы) вызовы для любого канала ввода-вывода, с которым он может работать.Если вы покопаетесь в искаженной кодовой базе, вся асинхронная логика будет на виду (учебник Крондо действительно хорош для приведенных примеров)
Позвольте мне использовать клавиатуру в качестве примера.
В коде синхронизации вы должны использовать input
или read
- , и программа приостановит , ожидая ввода этой строки (или клавиши).
В асинхронном коде (по крайней мере, в таких характерных реализациях, как витая) вы извлекаете дескриптор файла для «ввода» и регистрируете его с помощью функции обратного вызова, которая будет вызываться при изменении дескриптора файла, в асинхронный уровень на уровне ОСengine (select, poll, kpoll и т. д.)
Акт регистрации - которая почти не занимает времени ПОЗВОЛЯЕТ ВАМ запускать другую логику, покаЛогика клавиатуры ожидает события клавиатуры (см. строку stdio.StandardIO(keyboardobj,sys.stdin.fileno())
в конце моего примера кода в https://stackoverflow.com/a/30399317/3334178).
"[Это] наводит меня на мысль, что есть и другие способы использования отложенныхс асинхронным "
deferreds не волшебство. Это просто умные списки функций обратного вызова. Есть множество умных способов их объединения в цепочку, но в конце концов, они просто инструмент, который поможет вам воспользоватьсяиз лogic выше
"Это также говорит об асинхронности / ожидании, то есть только для Python 3, и я использую Python 2.7"
async
и await
- это всего лишь способ Python 3делать то, что было сделано в python2 с @defer.inlineCallbacks
и yield
.Эти системы представляют собой ярлыки, которые переписывают код так, что для считывателя код выглядит и действует как код синхронизации, но при его запуске код преобразуется в «зарегистрировать обратный вызов и переместитьна "flow
", когда я читаю о реакторе, он говорит, что все работает в основном потоке в реакторе.run () "
Да, потому что (как указано выше) асинхронность не оожидание ввода-вывода - его не о многопоточности или мультиобработке
Ваши последние несколько вопросов "точка отсрочки" и "как вы делаете асинхронный" чувствуют, что я ответил на них выше - но если нет, дайте мне знать в комментариях, и я изложу их.
Также ваш комментарий, запрашивающий "пример, в котором мы считаем от 1 до 10 в некоторой отложенной функции, в то время как мы считаем от a до z в главном потоке?" не имеет смысла, когда речь идет об асинхронности (и потому, что вы говорите о «потоке» - это другая конструкция, и потому что это обе (вероятные) задачи ЦП), но я приведу другой пример, который учитывается при просмотре для ввода с клавиатуры (что определенно имеет смысл, когда речь идет об асинхронности:
#!/usr/bin/env python
#
# Frankenstein-esk amalgam of example code
# Key of which comes from the Twisted "Chat" example
# (such as: http://twistedmatrix.com/documents/12.0.0/core/examples/chatserver.py)
import sys # so I can get at stdin
import os # for isatty
import termios, tty # access to posix IO settings
from twisted.internet import reactor
from twisted.internet import stdio # the stdio equiv of listenXXX
from twisted.protocols import basic # for lineReceiver for keyboard
from twisted.internet import task
class counter(object):
runs = 0
def runEverySecond():
counter.runs += 1
print "async counting demo: " + str(counter.runs)
# to set keyboard into cbreak mode - so keys don't require a CR before causing an event
class Cbreaktty(object):
org_termio = None
my_termio = None
def __init__(self, ttyfd):
if(os.isatty(ttyfd)):
self.org_termio = (ttyfd, termios.tcgetattr(ttyfd))
tty.setcbreak(ttyfd)
print ' Set cbreak mode'
self.my_termio = (ttyfd, termios.tcgetattr(ttyfd))
else:
raise IOError #Not something I can set cbreak on!
def retToOrgState(self):
(tty, org) = self.org_termio
print ' Restoring terminal settings'
termios.tcsetattr(tty, termios.TCSANOW, org)
class KeyEater(basic.LineReceiver):
def __init__(self):
self.setRawMode() # Switch from line mode to "however much I got" mode
def rawDataReceived(self, data):
key = str(data).lower()[0]
if key == 'q':
reactor.stop()
else:
print "--------------"
print "Press:"
print " q - to cleanly shutdown"
print "---------------"
# Custom tailored example for SO:56013998
#
# This code is a mishmash of styles and techniques. Both to provide different examples of how
# something can be done and because I'm lazy. Its been built and tested on OSX and linux,
# it should be portable (other then perhaps termal cbreak mode). If you want to ask
# questions about this code contact me directly via mail to mike at partialmesh.com
#
#
# Once running press any key in the window where the script was run and it will give
# instructions.
def main():
try:
termstate = Cbreaktty(sys.stdin.fileno())
except IOError:
sys.stderr.write("Error: " + sys.argv[0] + " only for use on interactive ttys\n")
sys.exit(1)
keyboardobj = KeyEater()
l = task.LoopingCall(runEverySecond)
l.start(1.0) # call every second
stdio.StandardIO(keyboardobj,sys.stdin.fileno())
reactor.run()
termstate.retToOrgState()
if __name__ == '__main__':
main()
(Я знаю, что технически я не использовал отложенное - но у меня не хватило времени - и этот случай слишком прост, чтобы действительно нуждаться в этом (у меня нигде нет цепочки обратных вызовов, что и является отложенным) для))