August 8, 2017·4 min read·engineeringpythonmaintenancecompatibility

Python 3.5.4 closes the branch to general bug fixes

Python 3.5.4 delivers its final general maintenance update before security-only support, including bytecode compatibility and process cleanup corrections.

Remaining on an interpreter version involves a support decision as well as a compatibility decision. Python 3.5.4 is the final general bugfix release of the 3.5 series. The August 8 release announcement says the branch now enters security-fixes-only mode. An application can continue to use the series, but ordinary defects no longer have the same route to an upstream maintenance release.

The distinction matters even when the application needs no newer language syntax. Runtime behavior includes process cleanup and compatibility with existing compiled code. This final update addresses both. Its candidate change record, included in the final release, provides concrete examples of the work that a general bugfix phase permits before the branch's maintenance scope narrows.

I approach Python through the capabilities its libraries provide, so a runtime upgrade is partly a question about those dependencies. A supported series is useful while dependencies constrain that choice. The end of general maintenance changes what can reasonably be expected from staying on it, even before security support ends.

Existing bytecode needs an explicit compatibility fix

Issue 29537 restores runtime compatibility with bytecode files generated by CPython 3.5.0 through 3.5.2. The release note identifies a malformed variant of the BUILD_MAP_UNPACK_WITH_CALL opcode that those versions may produce. The evaluation loop changes to avoid the problems that variant can cause when an interpreter executes the older bytecode.

This is a compatibility issue within a single Python feature series. Source code compatibility alone cannot describe it because the input being consumed is an existing bytecode file. An application may not have changed its source at all, yet an interpreter update can expose a difference in how the compiled form is processed. The fix preserves the ability to consume the forms already generated by the earlier releases named in the note.

The scope is specific. It does not establish that bytecode is a portable distribution format across arbitrary Python versions or implementations. It restores the documented compatibility case within CPython 3.5. That precision is useful when deciding whether a failure concerns application logic or the runtime's handling of a previously generated artifact.

Finishing a process operation includes its threads

Issue 30886 changes multiprocessing.Queue.join_thread() so it waits for completion even when the thread was started by the same process that created the queue. A method named for joining a thread needs to account for that ownership case. Returning without the intended wait can leave cleanup timing different from what the calling code expects.

Another queue correction, issue 30414, keeps the background _feed thread from leaving its main loop on an exception. The change record identifies the background worker as the component needing repair. Code submitting work to a queue depends on machinery that is not visible at the submission call, so a failure in that machinery can outlast the operation that first caused it.

The pool receives related maintenance under issue 29861. It releases references to completed tasks, their arguments, and their results as soon as they finish. That is a change in object lifetime, which can matter when arguments or results retain other objects. The note gives a concrete cleanup rule without claiming a universal reduction in application memory use.

These corrections affect different parts of multiprocessing. Waiting for a thread establishes completion, continuing a feeder loop preserves ongoing operation, and releasing references ends ownership of completed work. Grouping them under maintenance should not obscure the separate behaviors a program relies on.

Small timer values must remain nonzero

Issue 30807 corrects conversion of tiny values passed to signal.setitimer(). The release note uses 1e-6 as a valid nonzero interval for an interface with microsecond resolution. On some platforms, conversion could turn that value into a zero interval and disable the timer instead of scheduling it.

This failure changes the meaning of the request. A very short delay still asks the system to arrange a timer, while zero disables it. Rounding across that boundary therefore has a control effect beyond a small error in timing. The correction preserves a distinction already present in the interface's accepted values.

I prefer release notes that identify this kind of boundary explicitly. A description such as improved timer accuracy would miss the operational difference between a delayed signal and a disabled timer. The documented conversion problem explains why the patch matters to an application using small intervals without implying that the operating system guarantees exact delivery times.

The release also includes security maintenance, such as Windows subprocess environment handling and the Expat 2.2.1 update. Those fixes demonstrate the continuing importance of the branch while general maintenance ends. The release announcement limits future work to security fixes, so a developer encountering a non-security runtime defect after this point must account for that policy when choosing an interpreter series. Python 3.5.4 supplies the final general correction set under the broader maintenance policy, including compatibility and lifecycle fixes that do not require adopting new language constructs.