Skip to content

argparse: successive parsing wipes out nargs=? values #72920

Description

@adamjstewart
BPO 28734
Nosy @wm75, @adamjstewart

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 2016-11-18.15:41:15.800>
labels = ['invalid', 'type-bug', 'library']
title = 'argparse: successive parsing wipes out nargs=? values'
updated_at = <Date 2017-07-29.00:02:53.657>
user = 'https://github.com/adamjstewart'

bugs.python.org fields:

activity = <Date 2017-07-29.00:02:53.657>
actor = 'terry.reedy'
assignee = 'none'
closed = False
closed_date = None
closer = None
components = ['Library (Lib)']
creation = <Date 2016-11-18.15:41:15.800>
creator = 'ajstewart'
dependencies = []
files = []
hgrepos = []
issue_num = 28734
keywords = []
message_count = 4.0
messages = ['281128', '281137', '281138', '299354']
nosy_count = 4.0
nosy_names = ['bethard', 'paul.j3', 'wolma', 'ajstewart']
pr_nums = []
priority = 'normal'
resolution = 'not a bug'
stage = None
status = 'open'
superseder = None
type = 'behavior'
url = 'https://bugs.python.org/issue28734'
versions = ['Python 3.5']

Activity

  1. adamjstewart commented on Nov 18, 2016

    adamjstewartmannequin
    MannequinAuthor

    I'm writing a wrapper that optionally accepts a file and reads more options from that file. The wrapper then needs to pass all of these options and the file to another program (qsub). Here is a minimal example to reproduce the behavior I'm seeing:

    >>> import argparse
    >>> parser = argparse.ArgumentParser()
    >>> parser.add_argument('-a')
    >>> parser.add_argument('file', nargs='?')
    >>> args = parser.parse_args(['-a', '3', 'myFile'])
    >>> print(args)
    Namespace(file='myFile', a='3')
    >>> parser.parse_args(['-a', '4'], namespace=args)
    >>> print(args)
    Namespace(file=None, a='4')

    The behavior I expect is that the file should remain as 'myFile', but it is being wiped out. Is there any way to prevent this, or is this actually a bug?

    I can recreate this problem in Python 2.7 and 3.5.

  2. added
    stdlibStandard Library Python modules in the Lib/ directory
    type-bugAn unexpected behavior, bug, or error
    on Nov 18, 2016
  3. wm75 commented on Nov 18, 2016

    wm75mannequin
    Mannequin

    try this:
    parser.add_argument('file', nargs='?', default = argparse.SUPPRESS)

    I don't think this is a bug. The default for the default parameter is None so the behavior is consistent with the documentation.

  4. adamjstewart commented on Nov 18, 2016

    adamjstewartmannequin
    MannequinAuthor

    Works for me, thanks Wolfgang!

  5. paulj3 commented on Jul 27, 2017

    paulj3mannequin
    Mannequin

    The problem described here is restricted to ? and `*' positionals, and is caused by the subtle way in which 'empty' optional positionals are handled.

    The regular handling of defaults at the start of parse_known_args works fine. The default is only written to the namespace if something isn't there already.

         if not hasattr(namespace, action.dest):
             if action.default is not SUPPRESS:
                  setattr(namespace, action.dest, action.default)

    But a positional with ? or * is always 'seen' because an empty list of strings satisfies the nargs pattern. 'get_values()' has special handling for this case:

            if not arg_strings and action.nargs == OPTIONAL:
                ....
                    value = action.default

    That is, it replaces the empty list with the 'default'.

    But take_action(), which does the actual saving, is conditional:

                # take the action if we didn't receive a SUPPRESS value
                # (e.g. from a default)
                if argument_values is not SUPPRESS:
                    action(self, namespace, argument_values, option_string)

    That explains why 'default=SUPPRESS' solves this issue.

    It's enough to satisfy the OP's situation, but I don't think it's a robust fix.

    I don't have a patch idea yet, but this probably should be reopened so there's a record of the potential problem.

    More on the complications raised by these 'seen default actions' in

    http://bugs.python.org/issue18943

  6. reopened this on Jul 27, 2017
  7. transferred this issue fromon Apr 10, 2022
  8. serhiy-storchaka commented on Sep 25, 2024

    @serhiy-storchaka
    Member

    Closing this issue, because the reported case is unusual, the OP is satisfied with the workeraund, and changing the current behavior is really hard.

  9. moved this from Bugs to Doc issues in Argparse issueson Sep 25, 2024
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

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions