Showing content from http://mail.python.org/pipermail/python-dev/attachments/20131018/c2a9f295/attachment.html below:
<p dir="ltr"><br>
On 18 Oct 2013 09:05, "Guido van Rossum" <<a href="mailto:guido@python.org">guido@python.org</a>> wrote:<br>
><br>
> On Thu, Oct 17, 2013 at 3:51 PM, Oscar Benjamin <<a href="mailto:oscar.j.benjamin@gmail.com">oscar.j.benjamin@gmail.com</a>> wrote:<br>
>><br>
>> On 17 October 2013 20:01, Guido van Rossum <<a href="mailto:guido@python.org">guido@python.org</a>> wrote:<br>
>> > On Thu, Oct 17, 2013 at 11:55 AM, Oscar Benjamin<br>
>> > <<a href="mailto:oscar.j.benjamin@gmail.com">oscar.j.benjamin@gmail.com</a>> wrote:<br>
>> >><br>
>> >> On 17 October 2013 19:40, Xavier Morel <<a href="mailto:python-dev@masklinn.net">python-dev@masklinn.net</a>> wrote:<br>
>> >> > I think there's already a significant split between context managers<br>
>> >> > which handle the lifecycle of a local resource (file, transaction) and<br>
>> >> > those which purport to locally alter global-ish state (cwd,<br>
>> >> > decimal.localcontext, logging.captureWarnings, redirect_stdout).<br>
>> >> ><br>
>> >> > And the latter worries me (much more than the very localized behavior of<br>
>> >> > suppress) because I don't see any way to implement them safely and<br>
>> >> > correctly when mixing it with coroutines in today's Python (some of them<br>
>> >> > aren't even thread-safe), all of that while I expect coroutines will see<br>
>> >> > significantly more use in the very near future with yield from and<br>
>> >> > tulip's promotion of coroutine-style async.<br>
>> >><br>
>> >> I maybe misunderstanding how the coroutine-style async works but I<br>
>> >> would have thought that it would be as simple as: don't use<br>
>> >> global-state-restoring-context-managers around statements that yield<br>
>> >> control (it would be simpler if there was a good term for describing<br>
>> >> that kind of CM). That's simpler to implement and computationally<br>
>> >> cheaper than e.g. the thread-local state used by the decimal module.<br>
>> ><br>
>> > Context managers that actually save and restore *global* state are already<br>
>> > not thread-safe, so concluding they are also not coroutine-safe (or<br>
>> > task-safe?) seems a small step.<br>
>> ><br>
>> > I'd be more worried about context manager that use thread-local state --<br>
>> > there is no similar concept in Tulip.<br>
>><br>
>> It's unnecessary in Tulip. The need for thread-local state in e.g.<br>
>> decimal contexts is driven by the fact that multi-threaded execution<br>
>> switches in an uncontrollable way. Tulip specifically makes it<br>
>> possible to control the points at which a switch occurs making this<br>
>> safe (even if localcontext() wasn't thread-safe):<br>
>><br>
>> with decimal.localcontext() as ctx:<br>
>> ctx.prec = 100<br>
>> c = a + b<br>
>> # more synchronous decimal calculations<br>
>><br>
>> # State is restored before allowing other code to execute<br>
>> yield from save_in_database(c)<br>
>><br>
>> So it's fine to use global/thread-local state modifying/restoring<br>
>> context managers in Tulip as long as you don't yield control to other<br>
>> code within the with block. (unless I misunderstand - I lost track of<br>
>> Tulip some time ago).<br>
><br>
><br>
> You've got it exactly right.<br>
> <br>
>><br>
>> The issue with decimal.localcontext() and yield arises when using<br>
>> generators as much as coroutines e.g.:<br>
>><br>
>> def exact_sum(nums):<br>
>> start = Decimal(0)<br>
>> with decimal.localcontext() as ctx:<br>
>> ctx.traps[decimal.Inexact] = True<br>
>> for num in nums:<br>
>> try:<br>
>> total += Decimal(num)<br>
>> except decimal.Inexact:<br>
>> ctx.prec *= 2<br>
>> return total<br>
>><br>
>> The above is fine for computing the sum of a list of<br>
>> Decimals/ints/floats. However it fails if you pass in a generator that<br>
>> carelessly modifies the arithmetic context around yield calls:<br>
>><br>
>> def compute():<br>
>> with decimal.localcontext() as ctx:<br>
>> ctx.prec = 15<br>
>> ctx.traps[decimal.Inexact] = False<br>
>> yield a + b<br>
>> yield b - c<br>
>> # etc.<br>
>><br>
>> exact_sum(compute())<br>
>><br>
>> There needs to be a convention that either functions like exact_sum()<br>
>> mustn't assume continuity of the context between iterations or a<br>
>> function like compute() must restore before yielding. IMO the only<br>
>> sane approach for async coroutines is to say that if you yield or<br>
>> yield from then it is your responsibility to restore any temporarily<br>
>> altered global/thread-local state first.<br>
><br>
><br>
> Right again. The simplest rule to remember seems to be "don't use yield or yield-from inside a with-statement". You can relax it by limiting it to context managers that manage any kind of shared resource, but that is probably already too subtle: e.g. yielding inside "with open(file) as f" seems fine, but yielding inside "with lock" is problematic, since the other side might try to acquire the same lock, and deadlock.</p>
<p dir="ltr">Even the file case can be tricky - if you actually yield *the file* (rather than nothing or its contents), then the recipient may be surprised when it is later closed automatically.</p>
<p dir="ltr">It wouldn't surprise me if we see idioms to temporarily revert the effects of context managers start to grow in popularity once asyncio is released as part of 3.4.</p>
<p dir="ltr">Cheers,<br>
Nick.</p>
<p dir="ltr">><br>
> -- <br>
> --Guido van Rossum (<a href="http://python.org/~guido">python.org/~guido</a>)<br>
><br>
> _______________________________________________<br>
> Python-Dev mailing list<br>
> <a href="mailto:Python-Dev@python.org">Python-Dev@python.org</a><br>
> <a href="https://mail.python.org/mailman/listinfo/python-dev">https://mail.python.org/mailman/listinfo/python-dev</a><br>
> Unsubscribe: <a href="https://mail.python.org/mailman/options/python-dev/ncoghlan%40gmail.com">https://mail.python.org/mailman/options/python-dev/ncoghlan%40gmail.com</a><br>
><br>
</p>
RetroSearch is an open source project built by @garambo
| Open a GitHub Issue
Search and Browse the WWW like it's 1997 | Search results from DuckDuckGo
HTML:
3.2
| Encoding:
UTF-8
| Version:
0.7.4