base python: quadro Python trançado usado para código de programa de gravação exemplo nonblocking

Torcido é um framework de desenvolvimento baseado em modelo assíncrono e, portanto, o uso de bloqueadores não-programa torcida irá, naturalmente, ser de uso, aqui vamos nós para olhar em conjunto, utilizando framework Python torcida do programa de bloquear não-exemplo de código de escrita:
trançado é baseado no desenvolvimento de modo assíncrono quadro, assim o uso de bloqueadores não-programa torcida irá, naturalmente, ser de uso, aqui nos reunimos para olhar para o uso de Python torcida programa-quadro de bloquear não-exemplo de código de escrita:

# ~*~ Twisted - A Python tale ~*~
 
from time import sleep
 
# Hello, I'm a developer and I mainly setup Wordpress.
def install_wordpress(customer):
  # Our hosting company Threads Ltd. is bad. I start installation and...
  print "Start installation for", customer
  # ...then wait till the installation finishes successfully. It is
  # boring and I'm spending most of my time waiting while consuming
  # resources (memory and some CPU cycles). It's because the process
  # is *blocking*.
  sleep(3)
  print "All done for", customer
 
# I do this all day long for our customers
def developer_day(customers):
  for customer in customers:
    install_wordpress(customer)
 
developer_day(["Bill", "Elon", "Steve", "Mark"])

Prazo, os resultados são os seguintes:

$ ./deferreds.py 1
------ Running example 1 ------
Start installation for Bill
All done for Bill
Start installation
...
* Elapsed time: 12.03 seconds

Esta é a seção do código que é executado seqüencialmente. Quatro consumidores, uma pessoa precisa para instalar três segundos, em seguida, os quatro homens é de 12 segundos. Esse tratamento não é muito satisfatório, então olhamos para o segundo exemplo do uso de tópicos:

import threading
 
# The company grew. We now have many customers and I can't handle the
# workload. We are now 5 developers doing exactly the same thing.
def developers_day(customers):
  # But we now have to synchronize... a.k.a. bureaucracy
  lock = threading.Lock()
  #
  def dev_day(id):
    print "Goodmorning from developer", id
    # Yuck - I hate locks...
    lock.acquire()
    while customers:
      customer = customers.pop(0)
      lock.release()
      # My Python is less readable
      install_wordpress(customer)
      lock.acquire()
    lock.release()
    print "Bye from developer", id
  # We go to work in the morning
  devs = [threading.Thread(target=dev_day, args=(i,)) for i in range(5)]
  [dev.start() for dev in devs]
  # We leave for the evening
  [dev.join() for dev in devs]
 
# We now get more done in the same time but our dev process got more
# complex. As we grew we spend more time managing queues than doing dev
# work. We even had occasional deadlocks when processes got extremely
# complex. The fact is that we are still mostly pressing buttons and
# waiting but now we also spend some time in meetings.
developers_day(["Customer %d" % i for i in xrange(15)])

Executá-lo:

$ ./deferreds.py 2
------ Running example 2 ------
Goodmorning from developer 0Goodmorning from developer
1Start installation forGoodmorning from developer 2
Goodmorning from developer 3Customer 0
...
from developerCustomer 13 3Bye from developer 2
* Elapsed time: 9.02 seconds

Este pedaço de código é executado em paralelo, usando 5 segmentos de trabalho. 15 3s consumidor gastar significa que cada vez que um total de 45s, mas com uma execução paralela de cinco rosca gastou um total de única vez 9s. Este código é um pouco complicado, uma grande parte do código é usado para gerenciar concorrente, em vez de se concentrar em algoritmos ou lógica de negócios. Além disso, a saída do programa parece muito misturado, Tianjin também legível. Mesmo um código de multi-threaded simples também é difícil de escrever bem, então nos voltamos para usar Twisted:

# For years we thought this was all there was... We kept hiring more
# developers, more managers and buying servers. We were trying harder
# optimising processes and fire-fighting while getting mediocre
# performance in return. Till luckily one day our hosting
# company decided to increase their fees and we decided to
# switch to Twisted Ltd.!
 
from twisted.internet import reactor
from twisted.internet import defer
from twisted.internet import task
 
# Twisted has a slightly different approach
def schedule_install(customer):
  # They are calling us back when a Wordpress installation completes.
  # They connected the caller recognition system with our CRM and
  # we know exactly what a call is about and what has to be done next.
  #
  # We now design processes of what has to happen on certain events.
  def schedule_install_wordpress():
      def on_done():
        print "Callback: Finished installation for", customer
    print "Scheduling: Installation for", customer
    return task.deferLater(reactor, 3, on_done)
  #
  def all_done(_):
    print "All done for", customer
  #
  # For each customer, we schedule these processes on the CRM
  # and that
  # is all our chief-Twisted developer has to do
  d = schedule_install_wordpress()
  d.addCallback(all_done)
  #
  return d
 
# Yes, we don't need many developers anymore or any synchronization.
# ~~ Super-powered Twisted developer ~~
def twisted_developer_day(customers):
  print "Goodmorning from Twisted developer"
  #
  # Here's what has to be done today
  work = [schedule_install(customer) for customer in customers]
  # Turn off the lights when done
  join = defer.DeferredList(work)
  join.addCallback(lambda _: reactor.stop())
  #
  print "Bye from Twisted developer!"
# Even his day is particularly short!
twisted_developer_day(["Customer %d" % i for i in xrange(15)])
 
# Reactor, our secretary uses the CRM and follows-up on events!
reactor.run()

O resultado:

------ Running example 3 ------
Goodmorning from Twisted developer
Scheduling: Installation for Customer 0
....
Scheduling: Installation for Customer 14
Bye from Twisted developer!
Callback: Finished installation for Customer 0
All done for Customer 0
Callback: Finished installation for Customer 1
All done for Customer 1
...
All done for Customer 14
* Elapsed time: 3.18 seconds

Neste momento temos a perfeita execução do código e uma saída legível, e não usa threads. Lidamos com 15 consumidor paralelo, ou seja, teria exigido que o tempo de execução de 45s foi concluída dentro dos 3s. O truque é chamar-nos a todos a obstrução do sono () passam a ter torcido em pares task.deferLater () e a função de retorno. Agora que as operações de transformação efectuadas em outros lugares, que pode facilmente servir os 15 consumidores.
A operação de processamento acima mencionado têm lugar em algum outro lugar. Agora explique, operações aritméticas ainda ter lugar dentro da CPU, mas agora a velocidade de processamento da CPU é muito rápido em comparação com as operações de disco e de rede para. Portanto, para fornecer dados para a CPU ou a maior parte do tempo gasto enviando dados para a memória ou de outra CPU pela CPU. Nós usamos a operação non-blocking economiza tempo nesta área, por exemplo, task.deferLater () usa uma função de chamada de retorno quando a transferência de dados foi concluída será ativado.
Outro ponto muito importante é que a saída de Goodmorning do desenvolvedor Torcido e Bye do desenvolvedor torcido! Informação. Quando o código já começou a imprimir os dois pedaços de informação. Se o código é executado tão cedo para este lugar, então nós realmente começou a executar o aplicativo em que momento é? A resposta é que, para uma aplicação de torcida (incluindo Scrapy) está em execução reactor.run (para dentro). Antes de chamar esse método, você deve aplicar para cada cadeia diferidos pode ser utilizado no método pronto, então reactor.run () irá monitorar e ativar uma função de chamada de retorno.
Note-se que a regra principal reator é que você pode fazer qualquer coisa, contanto que ele é rápido o suficiente e é non-blocking.
Bem, agora, não é que parte do código para o gerenciamento de vários segmentos, mas esses retornos de chamada ainda parece confuso. Ele pode ser modificado de tal forma a:

# Twisted gave us utilities that make our code way more readable!
@defer.inlineCallbacks
def inline_install(customer):
  print "Scheduling: Installation for", customer
  yield task.deferLater(reactor, 3, lambda: None)
  print "Callback: Finished installation for", customer
  print "All done for", customer
 
def twisted_developer_day(customers):
  ... same as previously but using inline_install() instead of schedule_install()
 
twisted_developer_day(["Customer %d" % i for i in xrange(15)])
reactor.run()

Os resultados da execução do mesmo do exemplo anterior. E o papel deste código é o mesmo que o exemplo anterior, mas parece mais concisa. inlineCallbacks gerador pode usar algum mecanismo para fazer alguma função Python inline_install () para suspender ou execução currículo. inline_install () função em um objeto diferida e executado em paralelo para cada consumidor. Cada um rendimento de tempo quando executado vai parar na corrente inline_install () no exemplo, e, em seguida, até que o rendimento do objecto diferida para completar a operação de recuperação.
O único problema agora é que se tivermos mais de 15 consumidores, mas há, por exemplo, 10.000 consumidores tempo e como? Esta sequência de código também começará 10000 realizadas simultaneamente (tal como HTTP solicitações, a operação de gravação de base de dados, etc.). Pode haver nenhum problema para fazê-lo, mas também pode produzir uma variedade de falhas. Na aplicação há uma enorme solicitações simultâneas, tais como Scrapy, muitas vezes precisamos limitar o número de concorrentes a um nível aceitável diante. No exemplo a seguir, usamos task.Cooperator () para realizar esta função. Scrapy seu item Pipeline também utilizar o mesmo mecanismo para limitar o número de concorrente (isto é CONCURRENT_ITEMS conjunto):

@defer.inlineCallbacks
def inline_install(customer):
  ... same as above
 
# The new "problem" is that we have to manage all this concurrency to
# avoid causing problems to others, but this is a nice problem to have.
def twisted_developer_day(customers):
  print "Goodmorning from Twisted developer"
  work = (inline_install(customer) for customer in customers)
  #
  # We use the Cooperator mechanism to make the secretary not
  # service more than 5 customers simultaneously.
  coop = task.Cooperator()
  join = defer.DeferredList([coop.coiterate(work) for i in xrange(5)])
  #
  join.addCallback(lambda _: reactor.stop())
  print "Bye from Twisted developer!"
 
twisted_developer_day(["Customer %d" % i for i in xrange(15)])
reactor.run()
 
# We are now more lean than ever, our customers happy, our hosting
# bills ridiculously low and our performance stellar.
# ~*~ THE END ~*~

O resultado:

$ ./deferreds.py 5
------ Running example 5 ------
Goodmorning from Twisted developer
Bye from Twisted developer!
Scheduling: Installation for Customer 0
...
Callback: Finished installation for Customer 4
All done for Customer 4
Scheduling: Installation for Customer 5
...
Callback: Finished installation for Customer 14
All done for Customer 14
* Elapsed time: 9.19 seconds

Você pode ver a partir da saída acima, o processo parece ter cinco slots programa consumidor está em execução. A menos que um slot desocupado, não começará a processar pedidos no âmbito de um consumidor. Na presente forma de realização, o tempo de processamento é de três segundos, de modo que ele se parece com um punho 5 como lotes. O desempenho resultante com o uso de threads é o mesmo, mas desta vez apenas uma thread, o código mais simples e mais fácil de escrever código correto.

PS: função deferToThread sincronização sem bloqueio
Wisted de defer.Deferred (de twisted.internet adiar importação) pode retornar um objeto adiada.

Nota: deferToThread usar threads para alcançar, não recomendamos o uso excessivo
da função de sincronização se torna assíncrona (um retorno do diferido)
Twisted deferToThread (de twisted.internet.threads importar deferToThread) também retorna um objetos diferidos, mas a função de chamada de retorno em outro segmento tratamento, principalmente para o banco de dados / arquivo operação de leitura ...

# 代码片段
 
  def dataReceived(self, data):
    now = int(time.time())
 
    for ftype, data in self.fpcodec.feed(data):
      if ftype == 'oob':
        self.msg('OOB:', repr(data))
      elif ftype == 0x81: # 对服务器请求的心跳应答(这个是解析 防疲劳驾驶仪,发给gps上位机的,然后上位机发给服务器的)
        self.msg('FP.PONG:', repr(data))
      else:
        self.msg('TODO:', (ftype, data))
      d = deferToThread(self.redis.zadd, "beier:fpstat:fps", now, self.devid)
      d.addCallback(self._doResult, extra)

O exemplo a seguir completa aqui pode dar sua referência

# -*- coding: utf-8 -*-
 
from twisted.internet import defer, reactor
from twisted.internet.threads import deferToThread
 
import functools
import time
 
# 耗时操作 这是一个同步阻塞函数
def mySleep(timeout):
  time.sleep(timeout)
 
  # 返回值相当于加进了callback里
  return 3
 
def say(result):
  print "耗时操作结束了, 并把它返回的结果给我了", result
 
# 用functools.partial包装一下, 传递参数进去
cb = functools.partial(mySleep, 3)
d = deferToThread(cb) 
d.addCallback(say)
 
print "你还没有结束我就执行了, 哈哈"
 
reactor.run()

Finalmente, recomendamos uma ampla recolha de recursos de aprendizagem python, [clique para entrar] , aqui estão minha coleção antes de aprender a experiência, aprendendo caneta

Lembre-se, há um vislumbre de experiência corporativa, e acalmou a zero, com base em dados reais do projeto, podemos também abaixo da mensagem, não o

Entenda proposta, vamos estudar juntos o progresso

Publicado 47 artigos originais · ganhou elogios 34 · vê 60000 +

Acho que você gosta

Origin blog.csdn.net/haoxun08/article/details/104887486
Recomendado
Clasificación