Visitar URL original
Subprocess timeout causes output to be returned as bytes in text mode · Issue #87597 · python/cpython · GitHub
Skip to content

Subprocess timeout causes output to be returned as bytes in text mode #87597

Description

@macdjord
mannequin
BPO 43431
Nosy @giampaolo, @eryksun
Files
  • test_subprocess.py: Demonstration of issue
  • Note: these values reflect the state of the issue at the time it was migrated and might not reflect the current state.

    Show more details

    GitHub fields:

    assignee = None
    closed_at = None
    created_at = <Date 2021-03-08.05:41:46.323>
    labels = ['3.8', 'type-bug', 'library', '3.9', '3.10']
    title = 'Subprocess timeout causes output to be returned as bytes in text mode'
    updated_at = <Date 2021-03-30.18:57:45.244>
    user = 'https://bugs.python.org/macdjord'

    bugs.python.org fields:

    activity = <Date 2021-03-30.18:57:45.244>
    actor = 'eryksun'
    assignee = 'none'
    closed = False
    closed_date = None
    closer = None
    components = ['Library (Lib)']
    creation = <Date 2021-03-08.05:41:46.323>
    creator = 'macdjord'
    dependencies = []
    files = ['49856']
    hgrepos = []
    issue_num = 43431
    keywords = []
    message_count = 3.0
    messages = ['388257', '388265', '388272']
    nosy_count = 3.0
    nosy_names = ['giampaolo.rodola', 'eryksun', 'macdjord']
    pr_nums = []
    priority = 'normal'
    resolution = None
    stage = None
    status = 'open'
    superseder = None
    type = 'behavior'
    url = 'https://bugs.python.org/issue43431'
    versions = ['Python 3.8', 'Python 3.9', 'Python 3.10']

    Activity

    1. macdjord commented on Mar 8, 2021

      macdjordmannequin
      MannequinAuthor

      Passing the argument text=True to subprocess.run() is supposed to mean that any captured output of the called process is automatically decoded and retuned to the user as test instead of bytes.

      However, if you give a timeout and that timeout expires, the raised subprocess.TimeoutExpired exception will have the captured output as as bytes even if text mode is enabled.

      Test output:
      bash-5.0$ python3 test_subprocess.py
      Version and interpreter information: namespace(_multiarch='x86_64-linux-gnu', cache_tag='cpython-37', hexversion=50792432, name='cpython', version=sys.version_info(major=3, minor=7, micro=7, releaselevel='final', serial=0))
      Completed STDOUT Type: <class 'str'>
      Completed STDOUT Content: 'Start\nDone\n'
      Timeout STDOUT Type: <class 'bytes'>
      Timeout STDOUT Content: b'Start\n'

    2. added
      stdlibStandard Library Python modules in the Lib/ directory
      type-bugAn unexpected behavior, bug, or error
      on Mar 8, 2021
    3. eryksun commented on Mar 8, 2021

      @eryksun
      Contributor

      communicate() is incomplete, so decoding the output may fail. For example, say the encoding is UTF-8, and the last multibyte character sequence (2-4 bytes) is incomplete. Maybe communicate() should always set stdout_bytes and stderr_bytes attributes on the timeout exception, and, in text mode, try to decode the output as stdout and/or stderr. If decoding fails, set the decoded value to None.

      In Windows, run() tries to complete communication, which is dysfunctional in cases. I created bpo-43346 to propose changing the design in Windows, in order to address 3 cases that can cause subprocess.run() to ignore the given timeout. The proposed change also sets an incomplete read of stdout and stderr as bytes objects, regardless of text mode, because I was simply matching what POSIX does in this case.

    4. macdjord commented on Mar 8, 2021

      macdjordmannequin
      MannequinAuthor

      Eryk Sun: Well, I think step 1 should be to update the documentation for Python 3.7 through 3.10 on subprocess.run() and subprocess.TimeoutExpired to clearly state that TimeoutExpired.stdout and TimeoutExpired.stderr will be in bytes format even if text mode is set.

      If we went with the model of having stdout_bytes and attempting to decode into stdout, we'd want an option to ignore a trailing decoding error.

    5. 25 remaining items

    6. added
      pendingThe issue will be closed if no feedback is provided
      on Jan 5, 2024
    7. removed
      pendingThe issue will be closed if no feedback is provided
      3.13only security fixes
      on Jan 5, 2024
    8. LewisGaul commented on Jan 5, 2024

      @LewisGaul
      Contributor

      I don't think this should be closed, from my perspective this is just a bug, and should not have been documented as now changing it would be a breaking change (which would still be warranted in my opinion).

      I raised a PR addressing this (#95579 - not sure why it was moved to draft state), and a discussion following the pushback (https://discuss.python.org/t/pr-review-request-decode-subprocess-output-in-text-mode-when-timeout-is-hit/19594/2) which didn't get any input.

      This feels very much unfinished to me, and unfortunately remains an ugly wart for users who want to properly handle errors when using subprocess (especially in combination with mypy for type checking).

    9. gpshead commented on Jan 5, 2024

      @gpshead
      Member

      I understand your frustration, but existing code already depends on the behavior given it has been this way for 11+ years now so it isn't "just a bug" in that sense - thus documenting the existing behavior to save everyone the trouble of discovering it the hard way.

      I moved that PR to Draft as most PRs should really just start in Draft mode (a realtively new-to-github feature, we should use it more often) as that helps indicate that there are unresolved larger issues and it is unclear if the change as is, is even what we want. See my #95579 (comment) comment.

      It sounds like there is a potential way forward based on the last comment from @zooba on the PR - keeping both the bytes and decoding to text on demand via a new TimeoutExpired attribute for the purpose.

      I'm fine reopening this since you seem interested in working on it.

    10. reopened this on Jan 5, 2024
    11. removed
      type-bugAn unexpected behavior, bug, or error
      on Mar 13, 2025
    Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

    Metadata

    Metadata

    Assignees

    No one assigned

      Labels

      stdlibStandard Library Python modules in the Lib/ directorytopic-subprocessSubprocess issues.type-featureA feature request or enhancement

      Projects

      No projects

        Milestone

        No milestone

        Relationships

        None yet

        Development

        No branches or pull requests

        Issue actions