You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Negative run-time reported by subprocess.run's TimeoutExpired exception when setting timeout=0 #133089
importsubprocesssubprocess.run(['echo', 'hi'], timeout=0)
# subprocess.TimeoutExpired: Command '['echo', 'hi']' timed out after -0.00010189996100962162 seconds# subprocess.TimeoutExpired: Command '['echo', 'hi']' timed out after -4.819990135729313e-05 seconds
This is quite unexpected that the measured run-time can be negative
In general, it's unclear in the docs what behavior should have timeout=0. I would propose that it should disable timeout control, and should be equivalent to timeout=None.
But in any case, negative run-times are quite strange :)
if someone specifies an unrealistically small timeout such as 0 or 0.00001 they should expect to get a TimeoutError. timeout=0 should not disable the timeout. Requiring None for that is not a bug.
It'd be reasonable to raise ValueError if the timeout supplied were < 0 but I would not consider that a bugfix.
The tiny negative number in the error message in this case is due to timeout math being floating point, inexact, and fuzzy on posix it is calculated as an time delta of remaining time between steps and thus floating point precision can yield an odd looking result. the value in the error message is not the original timeout passed into the API call as that is not preserved and passed through into the self.wait(timeout=self._remaining_time(endtime)) call within Popen._communicate that raises in this specific case.
timeout=0 should not disable the timeout. Requiring None for that is not a bug.
I propose that semantics of this edge case is explained clearly in the docs. Because in different systems the semantics of timeout=0 is different, e.g. in bash export TMOUT=0 diables the auto-logout timeout
For the negative number, of course I realize that it's most likely an artifact of some calculation, but it is again very surprising to see it as end user and there might be a suspicion of some bug somewhere. I propose that it's mentioned in the docs somewhere - or clipped up to zero to fix up the semantics
(Allowing timeout=0 to have disabling semantics can simplify types to just being "float" instead of "float | None" in client user code, where the timeout value gets passed around many layers of indirection (including e.g. configs)
I also thought about the floating-point computation being flaky but AFAIR, the timeout is computed using a monotonic clock so that's surprising. Or maybe the monotonic clock was not used in this specific case?
Activity
pythongh-133089: Make `subprocess.run`'s behavior is same with 'timeo…
vadimkantorov commentedon Apr 30, 2025
Btw, even outside of unspecified behavior for
timeout=0, settingtimeoutto a very small value also prints negative time measurement:How can time measurement be negative? Is it indicative of some other bug related to execution time measurement?
gpshead commentedon May 3, 2025
if someone specifies an unrealistically small timeout such as 0 or 0.00001 they should expect to get a TimeoutError. timeout=0 should not disable the timeout. Requiring None for that is not a bug.
It'd be reasonable to raise ValueError if the timeout supplied were < 0 but I would not consider that a bugfix.
The tiny negative number in the error message in this case is due to timeout math being floating point, inexact, and fuzzy on posix it is calculated as an time delta of remaining time between steps and thus floating point precision can yield an odd looking result. the value in the error message is not the original timeout passed into the API call as that is not preserved and passed through into the self.wait(timeout=self._remaining_time(endtime)) call within
Popen._communicatethat raises in this specific case.vadimkantorov commentedon May 3, 2025
I propose that semantics of this edge case is explained clearly in the docs. Because in different systems the semantics of
timeout=0is different, e.g. in bashexport TMOUT=0diables the auto-logout timeoutFor the negative number, of course I realize that it's most likely an artifact of some calculation, but it is again very surprising to see it as end user and there might be a suspicion of some bug somewhere. I propose that it's mentioned in the docs somewhere - or clipped up to zero to fix up the semantics
(Allowing timeout=0 to have disabling semantics can simplify types to just being "float" instead of "float | None" in client user code, where the timeout value gets passed around many layers of indirection (including e.g. configs)
gpshead commentedon May 4, 2025
I think the awkward error message is fixable, i left a note on the PR to see if they want to try doing that.
gh-133089: Use original timeout value for `TimeoutExpired` when the f…
pythongh-133089: Use original timeout value for `TimeoutExpired` when…
gpshead commentedon May 5, 2025
thanks for the report and contributions!
[3.13] gh-133089: Use original timeout value for `TimeoutExpired` whe…
picnixz commentedon May 5, 2025
I also thought about the floating-point computation being flaky but AFAIR, the timeout is computed using a monotonic clock so that's surprising. Or maybe the monotonic clock was not used in this specific case?
pythongh-133089: Use original timeout value for `TimeoutExpired` when…