Jak napisać sekwencję obietnic w Pythonie?
Czy można napisać sekwencję obietnicy (lub zadań) używając tylko Python 3.6.1 Standard Library?
Na przykład Sekwencja obietnic w JavaScript jest zapisywana jako:
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();
Każda funkcja zwraca również obietnicę z wynikiem przetwarzania asynchronicznego, która zostanie rozwiązana / odrzucona przez następującą obietnicę.
Znam takie biblioteki jak promises-2.01b
oraz asyncio 3.4.3
i jestem szukam rozwiązania Python STL. Tak więc, jeśli muszę zaimportować bibliotekę non-STL, wolę używać RxPython.
3 answers
Oto podobny program wykorzystujący asyncio i async/await
syntax:
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()
EDIT: jeśli jesteś zainteresowany reaktywnymi strumieniami, możesz rozważyć użycie aiostream .
Oto prosty przykład:
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()
Więcej przykładów w dokumentacji .
Zastrzeżenie: jestem opiekunem projektu.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2019-10-04 10:50:26
Masz szczęście, Python 3.4 i nowsze zawierają asyncio
, chociaż funkcja, której szukasz ( Future ) jest dostępna w Pythonie 3.5 i nowszych.
Z twojego linku o asyncio
: "Ta wersja jest odpowiednia tylko dla Pythona 3.3, który nie zawiera asyncio w swoim stdlib."
Przykład:
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()
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-04-10 14:23:07
Możesz stworzyć swoją własną obietnicę klasową, nie jestem pythonowym dev ' em, ale próbowałem stworzyć coś podobnego do javascript.
class Promise:
def __init__(self, callback):
self.resolved = ''
self.rejected = ''
callback(self.resolve, self.reject)
def resolve(self, value):
self.resolved = value
def reject(self, value):
self.rejected = value
def then(self, callback):
if not self.rejected:
self.resolved = callback(self.resolved)
return self
def catch(self, callback):
if self.rejected:
self.rejected = callback(self.rejected)
return self
def myPromise(resolve, reject):
resolve(['Ana', 'Bia', 'Carlos', 'Daniel'])
def firstResolve(value):
return value[0]
def secondResolve(value):
print(value)
def firstReject(value):
print('error:', value)
p = Promise(myPromise)
p.then(firstResolve).then(secondResolve).catch(firstReject)
Obiecuję.wszystkie przykład
class Promise:
def __init__(self, callback):
self.resolved = ''
self.rejected = ''
if callable(callback):
callback(self.resolve, self.reject)
def resolve(self, value):
self.resolved = value
def reject(self, value):
self.rejected = value
def then(self, callback):
if not self.rejected:
self.resolved = callback(self.resolved)
return self
def catch(self, callback):
if self.rejected:
self.rejected = callback(self.rejected)
return self
def all(self, promises):
resolvedArray = []
rejectedArray = []
for promise in promises:
promise(self.resolve, self.reject)
if self.resolved:
resolvedArray += self.resolved
if self.rejected:
rejectedArray += self.rejected
break
self.resolved = resolvedArray
self.rejected = rejectedArray
return self
def myPromise1(resolve, reject):
resolve(['Ana'])
def myPromise2(resolve, reject):
resolve(['Bia'])
def myPromise3(resolve, reject):
resolve(['Carlos'])
def myPromise4(resolve, reject):
resolve(['Daniel'])
def allResolve(values):
print('without error: ', values)
def allReject(values):
print('with error: ', values)
p = Promise([])
p.all([myPromise1, myPromise2]).then(allResolve).catch(allReject)
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2021-01-22 16:02:34