[Python-ideas] Keyword only argument on function call

Ethan Furman ethan at stoneleaf.us
Wed Sep 12 09:59:44 EDT 2018


On 09/12/2018 05:17 AM, Steven D'Aprano wrote:

 > Indeed. Each time you call locals(), it returns a new dict with a
> snapshot of the current local namespace. Because it all happens inside
> the same function call, no external thread can poke inside your current
> call to mess with your local variables.
> 
> But that's different from setting function.__params__ to passed in
> arguments. By definition, each external caller is passing in its own set
> of arguments. If you have three calls to the function:
> 
>      function(a=1, b=2)  # called by A
>      function(a=5, b=8)  # called by B
>      function(a=3, b=4)  # called by C
> 
> In single-threaded code, there's no problem here:
> 
>      A makes the first call;
>      the interpreter sets function.__params__ to A's arguments;
>      the function runs with A's arguments and returns;
> 
>      only then can B make its call;
>      the interpreter sets function.__params__ to B's arguments;
>      the function runs with B's arguments and returns;
> 
>      only then can C make its call;
>      the interpreter sets function.__params__ to C's arguments;
>      the function runs with C's arguments and returns
> 
> 
> but in multi-threaded code, unless there's some form of locking, the
> three sets can interleave in any unpredictable order, e.g.:
> 
>      A makes its call;
>      B makes its call;
>      the interpreter sets function.__params__ to B's arguments;
>      the interpreter sets function.__params__ to A's arguments;
>      the function runs with B's arguments and returns;
>      C make its call;
>      the interpreter sets function.__params__ to C's arguments;
>      the function runs with A's arguments and returns;
>      the function runs with C's arguments and returns.
> 
> 
> We could solve this race condition with locking, or by making the pair
> of steps:
> 
>      the interpreter sets function.__params__
>      the function runs and returns
> 
> a single atomic step. But that introduces a deadlock: once A calls
> function(), threads B and C will pause (potentially for a very long
> time) waiting for A's call to complete, before they can call the same
> function.
> 
> I'm not an expert on threaded code, so it is possible I've missed some
> non-obvious fix for this, but I expect not. In general, solving race
> conditions without deadlocks is a hard problem.

I believe the solution is `threading.local()`, and Python would 
automatically use it in these situations.

--
~Ethan~


More information about the Python-ideas mailing list