Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > comp.lang.python > #86138 > unrolled thread
| Started by | pfranken85@gmail.com |
|---|---|
| First post | 2015-02-22 09:47 -0800 |
| Last post | 2015-02-23 18:30 +0200 |
| Articles | 6 — 3 participants |
Back to article view | Back to comp.lang.python
Question on asyncio pfranken85@gmail.com - 2015-02-22 09:47 -0800
Re: Question on asyncio Marko Rauhamaa <marko@pacujo.net> - 2015-02-22 23:21 +0200
Re: Question on asyncio pfranken85@gmail.com - 2015-02-23 01:48 -0800
Re: Question on asyncio Marko Rauhamaa <marko@pacujo.net> - 2015-02-23 15:27 +0200
Re: Question on asyncio Jonas Wielicki <jonas@wielicki.name> - 2015-02-23 16:05 +0100
Re: Question on asyncio Marko Rauhamaa <marko@pacujo.net> - 2015-02-23 18:30 +0200
| From | pfranken85@gmail.com |
|---|---|
| Date | 2015-02-22 09:47 -0800 |
| Subject | Question on asyncio |
| Message-ID | <52b94569-1480-4a05-a58f-13c2cb19229a@googlegroups.com> |
Hello!
I am just trying to get familiar with asyncio. It seems to be a good thing, however, I am still having troubles and feel pretty puzzled although I think I got the point what async IO means. This is the problem I am trying to accomplish:
I have some functions which are reading values from hardware. If one of the values changes, I want a corresponding notification to the connected clients. The network part shouldn't be the problem. Here is what I got so far:
@asyncio.coroutine
def check():
old_val = read_value_from_device()
yield from asyncio.sleep(2)
new_val = read_value_from_device()
# we may have fluctuations, so we introduce a threshold
if abs(new_val-old_val) > 0.05:
return new_val
else:
return None
@asyncio.coroutine
def runner():
while 1:
new = yield from check()
print(new)
loop = asyncio.get_event_loop()
loop.run_until_complete(update())
Is this the way one would accomplish this task? Or are there better ways? Should read_value_from_device() be a @coroutine as well? It may contain parts that take a while ... Of course, instead of print(new) I would add the corresponding calls for notifying the client about the update.
Thanks!
[toc] | [next] | [standalone]
| From | Marko Rauhamaa <marko@pacujo.net> |
|---|---|
| Date | 2015-02-22 23:21 +0200 |
| Message-ID | <8761atiqvt.fsf@elektro.pacujo.net> |
| In reply to | #86138 |
pfranken85@gmail.com: > I have some functions which are reading values from hardware. If one > of the values changes, I want a corresponding notification to the > connected clients. The network part shouldn't be the problem. Here is > what I got so far: > > @asyncio.coroutine > def check(): > old_val = read_value_from_device() > yield from asyncio.sleep(2) > new_val = read_value_from_device() > # we may have fluctuations, so we introduce a threshold > if abs(new_val-old_val) > 0.05: > return new_val > else: > return None > > @asyncio.coroutine > def runner(): > while 1: > new = yield from check() > print(new) In asyncio, you typically ignore the value returned by yield. While generators use yield to communicate results to the calling program, coroutines use yield only as a "trick" to implement cooperative multitasking and an illusion of multithreading. Thus, "yield from" in asyncio should be read, "this is a blocking state." > Is this the way one would accomplish this task? Or are there better > ways? Should read_value_from_device() be a @coroutine as well? It may > contain parts that take a while ... Of course, instead of print(new) I > would add the corresponding calls for notifying the client about the > update. How do you read a value from the hardware? Do you use a C extension? Do you want read_value_from_device() to block until the hardware has the value available or is the value always available for instantaneous reading? If the value is available instantaneously, you don't need to turn it into a coroutine. However, if blocking is involved, you definitely should do that. Depending on your hardware API it can be easy or difficult. If you are running CPython over linux, hardware access probably is abstracted over a file descriptor and a coroutine interface would be simple. Marko
[toc] | [prev] | [next] | [standalone]
| From | pfranken85@gmail.com |
|---|---|
| Date | 2015-02-23 01:48 -0800 |
| Message-ID | <5c9fa6a5-f92a-42a8-a760-9477f9d8d0d2@googlegroups.com> |
| In reply to | #86156 |
Hello Marko! Am Sonntag, 22. Februar 2015 22:21:55 UTC+1 schrieb Marko Rauhamaa: > In asyncio, you typically ignore the value returned by yield. While > generators use yield to communicate results to the calling program, > coroutines use yield only as a "trick" to implement cooperative > multitasking and an illusion of multithreading. Really? I saw several exmaples, where a coroutine returned a value which was then picked up from the yield from statement... > > Thus, "yield from" in asyncio should be read, "this is a blocking > state." > > > Is this the way one would accomplish this task? Or are there better > > ways? Should read_value_from_device() be a @coroutine as well? It may > > contain parts that take a while ... Of course, instead of print(new) I > > would add the corresponding calls for notifying the client about the > > update. > > How do you read a value from the hardware? Do you use a C extension? Do > you want read_value_from_device() to block until the hardware has the > value available or is the value always available for instantaneous > reading? > > If the value is available instantaneously, you don't need to turn it > into a coroutine. However, if blocking is involved, you definitely > should do that. Depending on your hardware API it can be easy or > difficult. If you are running CPython over linux, hardware access > probably is abstracted over a file descriptor and a coroutine interface > would be simple. The corresponding call is a call to the python smbus library. It includes several sleeps (even though they are only about 50ms). Therefore I think it is worthwhile to encapsulate it into a coroutine. However I am not quite sure, how I should call it and integrate it into the main loop. In particular, do I need something like the runner routine() with and infinite while loop or can just add the check() routine to the main loop, so that it gets executed regularly and call the corresponding notifier whenever the condition of the if statement is true? Thanks for your input!
[toc] | [prev] | [next] | [standalone]
| From | Marko Rauhamaa <marko@pacujo.net> |
|---|---|
| Date | 2015-02-23 15:27 +0200 |
| Message-ID | <87k2z8dagc.fsf@elektro.pacujo.net> |
| In reply to | #86204 |
pfranken85@gmail.com: > Hello Marko! > > Am Sonntag, 22. Februar 2015 22:21:55 UTC+1 schrieb Marko Rauhamaa: >> In asyncio, you typically ignore the value returned by yield. While >> generators use yield to communicate results to the calling program, >> coroutines use yield only as a "trick" to implement cooperative >> multitasking and an illusion of multithreading. > > Really? I saw several exmaples, where a coroutine returned a value > which was then picked up from the yield from statement... Actually, you might have better information in that regard than me. In my trials, I never used it like that. > The corresponding call is a call to the python smbus library. It > includes several sleeps (even though they are only about 50ms). > Therefore I think it is worthwhile to encapsulate it into a coroutine. Maybe. Then you'll probably have to rewrite smbus to work asyncio style. Those sleeps would then be done as "yield from" statements. Marko
[toc] | [prev] | [next] | [standalone]
| From | Jonas Wielicki <jonas@wielicki.name> |
|---|---|
| Date | 2015-02-23 16:05 +0100 |
| Message-ID | <mailman.19074.1424703937.18130.python-list@python.org> |
| In reply to | #86216 |
[Multipart message — attachments visible in raw view] — view raw
On 23.02.2015 14:27, Marko Rauhamaa wrote: > pfranken85@gmail.com: >> The corresponding call is a call to the python smbus library. It >> includes several sleeps (even though they are only about 50ms). >> Therefore I think it is worthwhile to encapsulate it into a coroutine. > > Maybe. Then you'll probably have to rewrite smbus to work asyncio style. > Those sleeps would then be done as "yield from" statements. > The manual has a word on this [1]. So I would suggest to use run_in_executor() instead of trashing and rewriting the whole smbus library. regards, jwi [1]: https://docs.python.org/3/library/asyncio-dev.html#handle-blocking-functions-correctly [2]: https://docs.python.org/3/library/asyncio-eventloop.html#asyncio.BaseEventLoop.run_in_executor
[toc] | [prev] | [next] | [standalone]
| From | Marko Rauhamaa <marko@pacujo.net> |
|---|---|
| Date | 2015-02-23 18:30 +0200 |
| Message-ID | <87a904d1za.fsf@elektro.pacujo.net> |
| In reply to | #86226 |
Jonas Wielicki <jonas@wielicki.name>: > On 23.02.2015 14:27, Marko Rauhamaa wrote: >> pfranken85@gmail.com: >>> The corresponding call is a call to the python smbus library. It >>> includes several sleeps (even though they are only about 50ms). >>> Therefore I think it is worthwhile to encapsulate it into a coroutine. >> >> Maybe. Then you'll probably have to rewrite smbus to work asyncio style. >> Those sleeps would then be done as "yield from" statements. >> > > The manual has a word on this [1]. So I would suggest to use > run_in_executor() instead of trashing and rewriting the whole smbus > library. Ok, that's always a fallback. I usually isolate such obnoxious function calls in a process pool. But that wouldn't be purely asyncio anymore. One of the main offenders is the database libraries. They should definitely provide nonblocking access. Marko
[toc] | [prev] | [standalone]
Back to top | Article view | comp.lang.python
csiph-web