web-dev-qa-db-ja.com

Pythonで一連のプロミスを書くにはどうすればよいですか?

onlyを使用して promise (またはタスク)のシーケンスを記述することは可能ですか? Python 3.6.1標準ライブラリ

たとえば、JavaScriptのシーケンスpromiseは次のように記述されます。

const SLEEP_INTERVAL_IN_MILLISECONDS = 200;

const alpha = function alpha (number) {
    return new Promise(function (resolve, reject) {
        const fulfill = function() {
            return resolve(number + 1);
        };

        return setTimeout(fulfill, SLEEP_INTERVAL_IN_MILLISECONDS);
    });
};

const bravo = function bravo (number) {
    return new Promise(function (resolve, reject) {
        const fulfill = function() {
            return resolve(Math.ceil(1000*Math.random()) + number);
        };
        return setTimeout(fulfill, SLEEP_INTERVAL_IN_MILLISECONDS);
    });
};

const charlie = function charlie (number) {
    return new Promise(function (resolve, reject) {
        return (number%2 == 0) ? reject(number) : resolve(number);
    });
};

function run() {
    return Promise.resolve(42)
        .then(alpha)
        .then(bravo)
        .then(charlie)
        .then((number) => {
            console.log('success: ' + number)
        })
        .catch((error) => {
            console.log('error: ' + error);
        });
}

run();

各関数 Promiseを返します 非同期処理結果で、すぐに続くPromiseによって解決/拒否されます。

promises-2.01basyncio 3.4.3 などのライブラリを認識しており、Python STLソリューションを探しています。したがって、非STLライブラリをインポートする必要がある場合は、代わりに RxPython を使用することをお勧めします。

18
JP Ventura

Asyncioとasync/await synthaxを使用した同様のプログラムを次に示します。

import asyncio
import random

async def alpha(x):
    await asyncio.sleep(0.2)
    return x + 1 

async def bravo(x):
    await asyncio.sleep(0.2)
    return random.randint(0, 1000) + x

async def charlie(x):
    if x % 2 == 0:
        return x
    raise ValueError(x, 'is odd')

async def run():
    try:
        number = await charlie(await bravo(await alpha(42)))
    except ValueError as exc:
        print('error:', exc.args[0])
    else:
        print('success:', number)

if __name__ == '__main__':
    loop = asyncio.get_event_loop()
    loop.run_until_complete(run())
    loop.close()

編集:リアクティブストリームに興味がある場合は、 aiostream の使用を検討してください。

以下に簡単な例を示します。

import asyncio
from aiostream import stream, pipe

async def main():
    # This stream computes 11² + 13² in 1.5 second
    xs = (
        stream.count(interval=0.1)      # Count from zero every 0.1 s
        | pipe.skip(10)                 # Skip the first 10 numbers
        | pipe.take(5)                  # Take the following 5
        | pipe.filter(lambda x: x % 2)  # Keep odd numbers
        | pipe.map(lambda x: x ** 2)    # Square the results
        | pipe.accumulate()             # Add the numbers together
    )
    print('11² + 13² = ', await xs)

if __name__ == '__main__':
    loop = asyncio.get_event_loop()
    loop.run_until_complete(main())
    loop.close()

ドキュメント のその他の例。

18
Vincent

運がよければ、Python 3.4以上にはasyncioが含まれていますが、探している機能( Future )はPython 3.5以降。

asyncioに関する独自のリンクから:「このバージョンは、Python 3.3、stdlibにasyncioを含まない)にのみ関連します。」

例:

import asyncio


async def some_coroutine():
    await asyncio.sleep(1)
    return 'done'


def process_result(future):
    print('Task returned:', future.result())


loop = asyncio.get_event_loop()
task = loop.create_task(some_coroutine())
task.add_done_callback(process_result)
loop.run_until_complete()
4
Wolph