Skip to content

Exceptions and arguments disappear when using argparse inside with statement #68258

Closed

Description

@invisibleroads
BPO 24070
Nosy @benjaminp, @bitdancer
Dependencies
  • bpo-9938: Add optional keyword argument exit_on_error to argparse.ArgumentParser
  • Files
  • argparse-with-exception.py
  • 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 = <Date 2015-04-28.18:29:16.040>
    created_at = <Date 2015-04-28.17:57:25.650>
    labels = ['type-bug', 'library']
    title = 'Exceptions and arguments disappear when using argparse inside with statement'
    updated_at = <Date 2015-05-06.17:52:11.294>
    user = 'https://bugs.python.org/invisibleroads'

    bugs.python.org fields:

    activity = <Date 2015-05-06.17:52:11.294>
    actor = 'r.david.murray'
    assignee = 'none'
    closed = True
    closed_date = <Date 2015-04-28.18:29:16.040>
    closer = 'benjamin.peterson'
    components = ['Library (Lib)']
    creation = <Date 2015-04-28.17:57:25.650>
    creator = 'invisibleroads'
    dependencies = ['9938']
    files = ['39227']
    hgrepos = []
    issue_num = 24070
    keywords = []
    message_count = 4.0
    messages = ['242192', '242196', '242692', '242693']
    nosy_count = 3.0
    nosy_names = ['benjamin.peterson', 'invisibleroads', 'r.david.murray']
    pr_nums = []
    priority = 'normal'
    resolution = 'duplicate'
    stage = 'resolved'
    status = 'closed'
    superseder = None
    type = 'behavior'
    url = 'https://bugs.python.org/issue24070'
    versions = ['Python 2.7', 'Python 3.4', 'Python 3.5']

    Activity

    1. invisibleroads commented on Apr 28, 2015

      invisibleroadsmannequin
      MannequinAuthor

      Exceptions and arguments disappear when using argparse inside a "with" statement. The behavior was confusing and frustrating because I could not pinpoint why certain arguments were missing or unrecognized.

      Unhandled exceptions inside the with statement typically trigger a traceback, unless __exit__ returns True, in which the exception is "swallowed" (https://www.python.org/dev/peps/pep-0343/).

      However, the NameError exception and tile_indices argument disappear because of a premature sys.exit (https://hg.python.org/cpython/file/default/Lib/argparse.py#l2385).

      """
      $ python exception-in-with.py
      EXPECTED
      Traceback (most recent call last):
        File "exception-in-with.py", line 51, in <module>
          abc  # !!!
      NameError: name 'abc' is not defined
      ACTUAL
      usage: exception-in-with.py [-h] --image_path PATH
      exception-in-with.py: error: argument --image_path is required
      
      $ python exception-in-with.py --image_path x
      EXPECTED == ACTUAL
      Traceback (most recent call last):
        File "exception-in-with.py", line 51, in <module>
          abc  # !!!
      NameError: name 'abc' is not defined
      
      $ python exception-in-with.py --image_path x --tile_indices 1
      EXPECTED
      Traceback (most recent call last):
        File "exception-in-with.py", line 51, in <module>
          abc  # !!!
      NameError: name 'abc' is not defined
      ACTUAL
      usage: exception-in-with.py [-h] --image_path PATH
      exception-in-with.py: error: unrecognized arguments: --tile_indices 1
      """
      from argparse import ArgumentParser
      
      
      class Starter(object):
      
          def __init__(self):
              self.argument_parser = ArgumentParser()
      
          def __enter__(self):
              return self
      
          def __exit__(self, exception_type, exception_value, exception_traceback):
              self.argument_parser.parse_args()
      
          def add_argument(self, *args, **kw):
              self.argument_parser.add_argument(*args, **kw)
      
      
      with Starter() as starter:
          starter.add_argument('--image_path', metavar='PATH', required=True)
          abc  # !!!
          starter.add_argument('--tile_indices', metavar='INTEGER')
      
    2. added
      stdlibStandard Library Python modules in the Lib/ directory
      type-bugAn unexpected behavior, bug, or error
      on Apr 28, 2015
    3. benjaminp commented on Apr 28, 2015

      @benjaminp
      Contributor

      I'm not sure why this is so surprising. parse_args in __exit__ raises a SystmExit, which the Python interpreter takes to mean the program is responsibly exiting. I don't think any other behavior would be reasonable. e.g. sys.exit() in an except clause shouldn't cause the exception to be printed.

    4. invisibleroads commented on May 6, 2015

      invisibleroadsmannequin
      MannequinAuthor

      The behavior may not be surprising from a technical perspective, but it is unintuitive.

      I think exceptions inside a with statement should trigger a traceback, unless you are saying that it is the responsibility of the author to catch and raise the exception inside __exit__, which feels to me like a workaround that is specific to parse_args.

    5. bitdancer commented on May 6, 2015

      @bitdancer
      Member

      What is happening here is that the __exit__ method gets passed the exception, and then instead of returning and allowing the exception to propagate and be printed, it raises SystemExit (via parse_args), which causes Python to immediately shut down, *before* __exit__ returns and the exception is propagated.

      So yes, you'd have to do something specific for argparse (which raises a SystemExit exception if parsing fails) if you want to do something non-normal with SystemExit. That is, you'll need to catch SystemExit.

      This is really a duplicate of bpo-9938.

    6. transferred this issue fromon Apr 10, 2022
    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/ directorytype-bugAn unexpected behavior, bug, or error

      Projects

      No projects

        Milestone

        No milestone

        Relationships

        None yet

        Development

        No branches or pull requests

        Issue actions