[Python-ideas] Explicit variable capture list

Guido van Rossum guido at python.org
Sun Jan 24 00:16:57 EST 2016


On Sat, Jan 23, 2016 at 7:22 PM, Nick Coghlan <ncoghlan at gmail.com> wrote:
> [...]
> For a practical example of this, consider the ThreadPoolExecutor
> example from the concurrent.futures docs:
> https://docs.python.org/3/library/concurrent.futures.html#threadpoolexecutor-example
>
> A scope-per-iteration construct makes it much easier to use a closure
> to define the operation submitted to the executor for each URL:
>
>     with concurrent.futures.ThreadPoolExecutor(max_workers=5) as executor:
>         # Start the load operations and mark each future with its URL
>         future_to_site = {}
>         for new site_url in sites_to_load:
>             def load_site():
>                 with urllib.request.urlopen(site_url, timeout=60) as conn:
>                     return conn.read()
>             future_to_site[executor.submit(load_site)] = site_url
>         # Report results as they become available
>         for future in concurrent.futures.as_completed(future_to_site):
>             site_url = future_to_site[future]
>             try:
>                 data = future.result()
>             except Exception as exc:
>                 print('%r generated an exception: %s' % (site_url, exc))
>             else:
>                 print('%r page is %d bytes' % (site_url, len(data)))
>
> If you try to write that code that way today (i.e. without the "new"
> on the first for loop), you'll end up with a race condition between
> the main thread changing the value of "site_url" and the executor
> issuing the URL open request.

I wonder if kids today aren't too much in love with local function
definitions. :-) There's a reason why executor.submit() takes a
function *and arguments*. If you move the function out of the for loop
and pass the url as a parameter to submit(), problem solved, and you
waste fewer resources on function objects and cells to hold nonlocals.
A generation ago most people would have naturally used such a solution
(since most languages didn't support the alternative :-).

-- 
--Guido van Rossum (python.org/~guido)


More information about the Python-ideas mailing list