Python 3.5.3 corrects assumptions in asynchronous networking
Python 3.5.3 updates asyncio's executor and event loop behavior alongside fixes to transport ownership and connection handling.
An event loop's behavior includes decisions that application code may never spell out. It chooses how to execute blocking work, associates callbacks with a running loop, and manages descriptors owned by transports. Python 3.5.3 changes several of those details. These maintenance fixes matter to applications that already use asynchronous Python and need the supported interpreter to behave consistently around its execution environment.
The release announcement dates Python 3.5.3 to January 17, 2017. The NEWS file shipped with the release records the changes that reached its release candidate and says there were no subsequent code changes before final. This is a maintenance release within Python 3.5, whose existing capabilities include the async and await syntax. The fixes develop the behavior around that programming model without requiring applications to adopt a new language series.
I appreciate Python's ability to express an asynchronous operation through ordinary control flow. The abstraction still depends on the event loop making defensible decisions about work that runs elsewhere. The executor changes are a good example of a patch release altering that relationship without changing a function's spelling.
The executor owns its worker default
Issue 26796 in the release NEWS says asyncio no longer configures the number of workers for its default thread pool executor. The distinction is about ownership of a default. Code submitting blocking work through the loop delegates execution to an executor, and the executor now supplies the worker default that asyncio previously configured.
This is relevant when an application treats the interpreter patch version as operationally transparent. A default belongs to a particular implementation, and leaving it unspecified does not fix its value forever. The NEWS entry does not promise a universal throughput improvement or a particular concurrency level for every machine. It identifies the component that now makes that choice.
An explicit executor remains a different case from an implicitly configured default. The important interpretation of this change is that an application relying on the default is accepting the executor's policy. Programs that need a particular concurrency bound should express that requirement in their configuration. That is a consequence of the changed ownership, not evidence that more workers are necessarily better.
The release also corrects get_event_loop() under issue 28613. When called from a coroutine or callback, it returns the current loop. Code running within a scheduled operation has an execution context already established by the scheduler. Returning the loop associated with that execution makes the lookup correspond to the operation that is actually running.
These fixes concern different resources, but both make implicit context easier to explain. The pool decides its own default capacity, while loop lookup within executing asynchronous code refers to its current loop. Neither change removes the need to distinguish asynchronous work from blocking work executed in a thread.
Transports and descriptors have an ownership relationship
The release NEWS records a RuntimeError when a transport's file descriptor is used with add_reader, add_writer, or related operations. Issue 28369 makes this conflict visible. A transport already participates in the event loop's management of its descriptor, so registering separate descriptor callbacks involves two ways of controlling the same underlying resource.
A failure at that boundary is useful because the conflicting registrations otherwise sit below the application protocol. A program may appear to be adding a callback while changing the machinery that its transport depends on. Rejecting the operation gives the application a concrete error associated with that misuse.
Connection handling receives other corrections. Issue 27906 addresses socket accept exhaustion during high TCP traffic. Issue 28176 fixes a callback race in the selector loop's sock_connect. These are different from changing application-level protocol handling. They concern the scheduler and socket operations on which that handling depends.
The same maintenance set fixes an SSL hang when the connection closes before its handshake completes, recorded as issue 28990. A peer can terminate a connection before the application has a usable secured stream. The asynchronous operation must account for that termination while it is still establishing the connection. The fix concerns completing that failure path rather than changing what constitutes a successful handshake.
Maintenance includes security policy
The library changes extend beyond asyncio. The SSL module removes 3DES from its default cipher list in response to the Sweet32 attack, recorded as issue 27850 and CVE-2016-2183. A default cipher list is policy consumed by applications that have not supplied an alternative. Updating that policy changes the choices available to those applications without requiring a new TLS call in their source.
The NEWS also records protection against HTTPoxy. Under issue 27568, urllib ignores HTTP_PROXY when REQUEST_METHOD indicates CGI execution. That conditional matters because an environment variable can have different origins in different execution arrangements. Treating a CGI-derived value as proxy configuration would cross the intended boundary between request input and client configuration.
I place more weight on these documented behavior changes than on the patch number's apparent size. Python's standard library connects application code to operating-system resources and network peers. A supported branch needs corrections at those boundaries even when its syntax and general programming model remain familiar.
The release contains no code changes after its candidate, according to the tagged NEWS. That makes the candidate's change list the relevant account of what final delivers. For asyncio users, the practical result includes a revised default executor policy, corrected current-loop lookup, and explicit rejection of descriptor registrations that conflict with transport ownership.