Python での一連の約束
このチュートリアルでは、Python で一連の promise を作成する方法を説明します。 まず、Python での非同期プログラミングについて説明します。
次に、Python のコールバック関数について説明します。 最後に、実際のトピックに入る前に、Python での try/except
について簡単に説明し、次に Python での一連の約束について説明します。
Python での非同期プログラミング
この記事では、オペレーティング システム スレッドの基本的な概念を理解していることを前提としています。 スレッドの予備知識がない場合は、前提条件として オペレーティング システムのスレッド を読むことができます。
非同期プログラミングでは、複数のスレッドを並行して実行できますが、メイン プログラム (通常はメイン/マネージャー スレッドと呼ばれます) は複数のワーカー スレッドを作成できます。 通常、メイン スレッドは、タスクの完了後にメイン スレッドに通知するワーカー スレッドを待機します。
通常のプログラミングとは異なり、競技まで制御を保持する代わりに、非同期関数は一時停止し、他の関数 (スレッド) を並行して実行できるようにします。
Python での非同期プログラミングについて説明し、例を示します。 ただし、関連する同期コードを最初に確認することをお勧めします。 このコードは、比較によって理解を深めるのに役立ちます。
def count():
for i in range(5):
print(i, end=" ")
def main():
count()
count()
count()
main()
ここでは、count
関数を 3 回続けて呼び出します。 出来上がりは期待通り。
0 1 2 3 4 0 1 2 3 4 0 1 2 3 4
最初の count
関数の出力、続いて count
関数の 2 番目の呼び出しの出力、最後に最後の count
関数の出力が表示されます。
Python の asyncio
ライブラリを使用すると、Python で非同期プログラムを実行できます。 非同期プログラミングの最初の要件は、関数を待機可能なオブジェクトとして設計することです。
標準関数を awaitable オブジェクトに変換するには、2つの要件があります。 1つ目は、async
キーワードを (def
キーワードの前に) 使用して、ルーチン関数の代わりに非同期関数を作成することです。
2 番目の要件は、非同期関数内で sleep
関数を呼び出し、現在の関数を中断し、他の関数を制御することです。
sleep
ステートメントは、関数が正確にサスペンド状態になるコード内の特定のポイントです。 非同期プログラミングの 2 番目の要件は、待機可能なオブジェクト (非同期関数) を呼び出すときに await
を追加することです。 そうしないと、エラーが発生します。
await
キーワードは、イベント ループに現在の関数を一時停止して、他の関数に実行時間を与えるように指示します。
3つ目の要件は、gather
関数を呼び出して、待機可能なオブジェクト (非同期関数) を渡すことです。 gather
関数は、これらの関数を順番に実行しますが、同時に実行します。
これは、最初の関数が最初に開始され、しばらくすると、2 番目の関数も並行して開始されることを意味します。 同様に、すべての非同期関数が 1つずつ同時に実行を開始します。
では、コードを見てみましょう。
import asyncio
async def count():
for i in range(5):
print(i, end=" ")
await asyncio.sleep(0.5)
async def main():
await asyncio.gather(count(), count(), count())
if __name__ == "__main__":
asyncio.run(main())
ここでは、以前のコードを非同期コードに変換し、特定の追加を行いました。 最初の行で、asyncio
ライブラリがインポートされます。
async
キーワードは、すべての関数の先頭に追加されます。
count
関数に sleep
関数呼び出しが追加されました。 await
キーワードは、main
関数を含むすべての関数呼び出しに追加されます。
最後に、gather
関数が main
で呼び出され、そこで count
関数が複数回呼び出され、各関数呼び出しが個別のスレッドとして示されます。
gather
関数を使用して、待機可能なオブジェクトを追加して、同時に実行する非同期関数のグループを形成します。 このコードの出力を見てみましょう。
0 0 0 1 1 1 2 2 2 3 3 3 4 4 4
出力では、すべてのスレッドが並列に実行され、完全に実行されるのではなく、非同期出力が生成されることがわかります。
同じ関数を複数回呼び出すと混乱する場合があります。 これは、異なる関数を並行して実行する別の例です。
import asyncio
async def count1():
for i in range(10):
print(i, end=" ")
await asyncio.sleep(0.5)
async def count2():
for i in range(50, 60):
print(i, end=" ")
await asyncio.sleep(0.5)
async def main():
await asyncio.gather(count1(), count2())
asyncio.run(main())
このコードの出力は次のとおりです。
0 50 1 51 2 52 3 53 4 54 5 55 6 56 7 57 8 58 9 59
ここでも、両方の機能が同時に実行されています。
コールバック関数
コールバックは別の関数に (引数として) 渡されます。 他の関数は、その定義のどこかでこの関数をコールバックすることになっています。
ただし、呼び出しポイントは、別の関数がどのように定義されているかによって異なります。
ここに、コールバック関数に関連する簡単なコーディング例があります。
import random as r
def callback1(s):
print(f"******* {s} *******")
def callback2(s):
print(f"^^^^^^^ {s} ^^^^^^^")
def print_through_callback(message, f1, f2):
if r.randint(0, 1) == 0:
f1(message)
else:
f2(message)
def main():
print_through_callback("Callback Example", callback1, callback2)
main()
このコードでは、print
関数に 3つのパラメーターがあります。 2 番目と 3 番目のパラメーターは関数名です。
main
では、2つの関数を渡し、コードはランダムに 1つを呼び出します。 このコードを複数回実行すると、両方の関数がランダムに呼び出されることがわかります。
Python の try/except
Python は例外処理も提供します。 Python では、コードをテストするための try
ブロックがあります。 例外の可能性があり、except
ブロックで例外を処理できます。
ゼロ除算が定義されておらず、プログラム (ほぼすべてのプログラミング言語) がクラッシュすることは誰もが知っています。 ゼロ除算を呼び出すとき。 わからない場合は、このコードを試してください。
def main():
x = int(input("Enter any number:"))
print(2 / x)
main()
ゼロを入力して結果を確認します。 プログラムがクラッシュします。 コードのクラッシュは悪いことであり、例外処理を通じて回避する必要があります。
例外処理を含む同じコードを参照してください。
def main():
try:
x = int(input("Enter any number:"))
print(2 / x)
except:
print("Divide by zero is not defined")
main()
このコードを実行してゼロ以外の値を入力する必要があります。 print (2/x)
内に書かれた除算演算の結果が得られます。 ゼロを入力すると、プログラムはクラッシュの代わりにゼロによる除算は定義されていません
というメッセージを表示します。
Python での一連の約束
コールバック関数は通常の関数と同じです。 ただし、その使用方法は異なります。
実行に時間がかかる重い関数を検討してください。 通常、このような関数は非同期に作成されます。
非同期関数はバックグラウンドで実行され、特定の時間が経過すると完了しますが、他の関数は並行して開始されます。 ただし、重い関数を実行した後に関数を実行したい場合は、コールバック関数を使用することを選択します。
ただし、そのようなタスクの完了には問題があります。 タスクが完了する前に例外をスローした場合はどうなりますか?
タスクが正常に完了した後に関数が確実に呼び出されるようにするには、promise と非同期プログラミングが必要です。
約束
promise は、非同期関数の成功または失敗 (失敗) 完了を表すオブジェクトです。
Promise オブジェクトは、非同期関数からの結果の値も表します。 promise は、複数のコールバックに関連する問題を管理するために使用されます。
promise
API を使用して、Python で一連の promise を実行できます。 ただし、Python では async/await
を使用して同じ目的を達成できます。
Python で非同期関数を実装するには、非同期関数で asyncio
ライブラリを使用する必要があります。 上記ですでに説明した await
キーワードを使用して、関数を順番に呼び出すことができます。
最後に、try/except
ブロックを使用しています。 まず、コードと出力を見てください。
後で、try/except
ブロックの目的について説明します。
import asyncio
import random as r
async def f1(x):
await asyncio.sleep(1)
return x ** 2
async def f2(x):
await asyncio.sleep(1)
return x / 2
async def f3(x):
if r.randint(0, 1) == 0:
return x
raise ValueError(x)
async def run():
try:
value = await f3(await f2(await f1(r.randint(5, 9))))
except ValueError as exception:
print("Exception Occurred:", exception.args[0])
else:
print("No Exception:", value)
if __name__ == "__main__":
loop = asyncio.get_event_loop()
loop.run_until_complete(run())
loop.close()
以下は、上記の Python スクリプトを 5 回実行した結果をまとめたものです。
No Exception: 12.5
Exception Occurred: 12.5
Exception Occurred: 32.0
No Exception: 18.0
No Exception: 40.5
出力は、非同期操作で成功または失敗する可能性があることを示しているだけです。 したがって、try
ブロック内の関数呼び出しの後に、コールバック関数のステートメントを配置できます。
正常に完了した場合、コードはコールバック関数を実行します。 失敗した場合、コントロールは except
ブロックに移動し、コールバック関数を無視します。
このようにして、Python で一連の promise を処理できます。 正常に完了した場合は、コールバック関数を実行します (これは、必要なタスクの正常な完了に依存します)。 それ以外の場合は、コールバック関数を実行する必要はありません。