ツイストは、非同期モデルベースの開発フレームワークであるため、非ブロックツイストプログラムの使用は、当然、我々が一緒に非ブロック書き込みコード例のプログラムのPythonのツイストフレームワークを使用して見に来て、ここで、使用されるであろう:
ツイストは、非同期モードの開発に基づいていますフレームワークは、非ブロックツイストプログラムのように使用することは、当然、ここで我々は、非ブロッキング書き込みコードサンプルのPythonのツイストフレームワークプログラムの使用を見て一緒に来て、使用されるであろう。
# ~*~ 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"])
ファイル名を指定して実行、次のような結果は次のとおりです。
$ ./deferreds.py 1
------ Running example 1 ------
Start installation for Bill
All done for Bill
Start installation
...
* Elapsed time: 12.03 seconds
これは、順次実行されるコードのセクションです。四人の消費者は、人が3秒をインストールする必要があり、その後、4人の男性は12秒です。このような治療は非常に満足のいくものではないので、我々はスレッドを使用しての第二の例を見てみましょう。
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)])
それを実行します。
$ ./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
コードのこの部分は、5つのワーカースレッドを使用して、並行して実行されます。15の3Sは、消費者それぞれの時間は45秒の合計が、5スレッドの並列実行でのみ9S時間の合計を過ごしたという手段を過ごします。このコードは少し複雑で、コードの大部分は、むしろアルゴリズムやビジネスロジックに焦点を当てよりも、同時を管理するために使用されます。さらに、プログラムの出力は、非常に複雑に見えますが、天津にも読めます。でも、簡単なマルチスレッドコードは、私たちがツイストを使用するようになったので、うまく書くことも困難です。
# 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()
結果:
------ 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
今回我々は、コードの完璧な実行と読み込み可能な出力を得て、スレッドを使用しません。私たちは、3秒以内に完了された45秒の実行時間を必要とした、と言うことです15パラレル消費者、に対処します。トリックは、すべてのピアtask.deferLaterでねじれによって置き換えられ、睡眠の妨害()()とコールバック関数たちを呼び出すことです。今、処理動作が他の場所で行われることを、我々は難なく両方の15の消費者にサービスを提供することができます。
前述の処理動作は、いくつかの他の場所で行われます。今、算術演算は、まだCPU内で行われる、説明したが、今CPUの処理速度が用ディスクおよびネットワーク運用に比べて非常に高速です。そのため、CPUにデータを提供したり、ほとんどの時間は、CPUによって、メモリまたは他のCPUへのデータ送信を過ごしました。我々は、例えば、非ブロッキング動作はこの分野で時間を節約使用、task.deferLater()は、データ転送が有効になり完了したコールバック関数を使用します。
別の非常に重要な点は、ツイストの開発者からのツイストの開発者とバイバイからグッドモーニングの出力!情報。コードは、すでに2つの情報をプリントアウトを開始したとき。コードがこんなに早くこの場所に実行されている場合は、私たちは本当にそれが何であるかを時間にアプリケーションを実行するために始めましたか?答えは(Scrapy含む)ツイストアプリケーションに対してreactor.run()の内部を実行している、ということです。このメソッドを呼び出す前に、あなたがして(reactor.run、すぐに使用されるかもしれない各繰延チェーンに適用する必要があります)メソッドは、監視し、コールバック関数が有効になります。
原子炉主なルールは、それが十分な速さであると、非ブロッキングであるとして、あなたがいる限り、何でもできるということであることに注意してください。
さて、複数のスレッドを管理するためのコードの一部ではありませんが、これらのコールバックはまだ乱雑に見えます。このような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()
前の例と同じように実行した結果。そして、このコードの役割は、前の例と同じであるが、それはより簡潔に見えます。inlineCallbacks発電機は、一時停止または再開実行するためにいくつかのPython inline_install()関数を作るために、いくつかのメカニズムを使用することができます。inline_install()繰延オブジェクトに機能し、各消費者のために並列に実行されます。実行するたび収量は、インスタンス上の現在のinline_install()で停止し、その後、繰延オブジェクトの収率は、回復操作を完了するまで。
唯一の問題は、今私たちは15人の以上の消費者を持っていますが、例えば、ある、万消費者の時間とどのようならばということでしょうか?また10000を開始するこのコード配列は、(例えば、HTTPリクエスト、データベースの書き込み動作、等のような)を同時に行います。そうする問題はないかもしれないが、また故障の様々なを生成することができます。このようScrapyとして巨大な同時要求があるアプリケーションでは、私たちはしばしば上許容可能なレベルまで同時の数を制限する必要があります。以下の例では、この機能を達成するためにtask.Cooperator()を使用します。Scrapyその項目パイプラインは、また、同時(すなわちCONCURRENT_ITEMSセット)の数を制限するために、同じメカニズムを使用します。
@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 ~*~
結果:
$ ./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
あなたは上記の出力から見ることができ、プロセスは、消費者プログラムが実行されている5つのスロットを持っているようです。スロットが空いていない限り、それは消費者の下で要求の処理を開始しません。それはバッチとしてハンドル5のように見えるので、本実施形態では、処理時間は、3秒です。スレッドを使用した結果、性能は同じですが、今回は一つのスレッドのみ、よりシンプルかつ簡単にコードが正しいコードを書くこと。
PS:ノンブロッキングdeferToThread同期機能
(twisted.internetインポート延期から)defer.Deferredのwistedは遅延オブジェクトを返すことができます。
注:deferToThreadの使用スレッドはの過度の使用はお勧めしません、達成するための
同期機能は、(リターン繰延)非同期になり
ツイストのdeferToThread(twisted.internet.threadsからはdeferToThreadをインポート)も繰延オブジェクトを返しますが、別のスレッドでコールバック関数主にデータベース/ファイルの読み出し動作のための治療、...
# 代码片段
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)
ここでは、次の完全な例では、あなたの参照を与えることができます
# -*- 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()
最後に、我々は非常に広いPythonの学習リソースの収集をお勧めします、[入力する]をクリック]ここでは、私のコレクションは、経験を学習ペンを学ぶ前にあります
我々はまた、メッセージではなく、以下のことができ、そこに企業の経験の兆しがあり、実際のプロジェクトデータに基づいてゼロに沈静化し、覚えておいてください
提案を理解し、我々は進歩を一緒に勉強します