This issue tracker has been migrated to GitHub, and is currently read-only.
For more information, see the GitHub FAQs in the Python's Developer Guide.

Title: argparse should accept bytes arguments as originally passed
Type: behavior Stage: resolved
Components: Library (Lib) Versions: Python 3.4, Python 3.5
Status: closed Resolution: not a bug
Dependencies: Superseder:
Assigned To: Nosy List: paul.j3, underrun, zach.ware
Priority: normal Keywords:

Created on 2014-05-02 17:10 by underrun, last changed 2022-04-11 14:58 by admin. This issue is now closed.

Messages (4)
msg217761 - (view) Author: Derek Wilson (underrun) Date: 2014-05-02 17:10
If I create an argument parser like:

parser = argparse.ArgumentParser()
parser.add_argument('somebytes', type=bytes, help='i want some bytes')

the parse_args() call will raise an exception printing usage info indicating that an "invalid bytes value" was passed if any of the bytes on the command line are >127.

if i'm specifying that i want bytes then i should expect that the argument should be interpreted as bytes and not text.

I get that #8776 was closed because it makes sense not to clutter up internals, but in this instance i am building a command line parser and telling it exactly what i expect. if the solution from #8776 of os.fsencode(sys.argv) will definitely always work then argparse should do this internally if i tell it i expect bytes on the command line.
msg219250 - (view) Author: paul j3 (paul.j3) * (Python triager) Date: 2014-05-28 04:11
Two points to keep in mind:

'argparse' works with 'sys.argv[1:]'.  If that does not contain what you want, then you can pass your own 'argv' to 'parse_args'.

'type=bytes' means, call the builtin 'bytes' function with one of the argv strings. If 'bytes' does not handle the string as you want, then you need to write your own function.
msg219251 - (view) Author: paul j3 (paul.j3) * (Python triager) Date: 2014-05-28 04:33
'invalid bytes value' is the error message generated by 'argparse'.  The underlying error (for a string like 'xxx') is:

    TypeError: string argument without an encoding

You could use 'bytes' if you somehow supply the encoding, as in:

    def mybytes(astr):
       return bytes(astr, 'utf-8')
msg219722 - (view) Author: Zachary Ware (zach.ware) * (Python committer) Date: 2014-06-03 21:11
The type parameter of ArgumentParser is a callable that will be called with the value of some member of sys.argv, it does *not* specify what the returned type will be.  You can just use os.fsencode as the type argument:

>>> import os
>>> import argparse
>>> p = argparse.ArgumentParser()
>>> p.add_argument('somebytes', type=os.fsencode, help='i want some bytes')
_StoreAction(option_strings=[], dest='somebytes', nargs=None, const=None, default=None, type=<function _fscodec.<locals>.fsencode at 0x00677AE0>, choices=None, help='i want some bytes', metavar=None)
>>> p.parse_args(['test'])
>>> p.parse_args([os.fsdecode(b'\xde\xad\xbe\xef')])
Date User Action Args
2022-04-11 14:58:03adminsetgithub: 65615
2015-04-11 02:07:43zach.waresetstatus: open -> closed
resolution: not a bug
stage: resolved
2014-06-03 21:11:39zach.waresetnosy: + zach.ware
messages: + msg219722
2014-05-28 04:33:38paul.j3setmessages: + msg219251
2014-05-28 04:11:19paul.j3setnosy: + paul.j3
messages: + msg219250
2014-05-02 17:10:38underruncreate