user45893
user45893

Reputation: 733

Argparse in Jupyter Notebook throws a TypeError

Using argparse in a Jupyter Notebook throws a TypeError. The same code works fine if I execute the same code as a script. MWE:

import argparse

parser = argparse.ArgumentParser(description='Foo')
parser.add_argument('--name', '-n', default='foo', help='foo')

args = parser.parse_args()

Result:

TypeError: 'level' is an invalid keyword argument for this function

Upvotes: 7

Views: 6067

Answers (3)

hpaulj
hpaulj

Reputation: 231665

When I run your code in a Notebook, I get an argparse usage error message:

usage: ipykernel_launcher.py [-h] [--name NAME]
ipykernel_launcher.py: error: unrecognized arguments: -f /run/user/1000/jupyter/kernel-a6504c0c-bed2-4405-8704-c008f52dcba6.json

With a print(sys.argv) I get

['/home/paul/.local/lib/python3.6/site-packages/ipykernel_launcher.py', '-f', '/run/user/1000/jupyter/kernel-a6504c0c-bed2-4405-8704-c008f52dcba6.json']

sys.argv, which parser parses, contains the values used to launch the Notebook server, which this particular parser is not setup to handle.

parser.parse_known_args() displays:

(Namespace(name='foo'),
 ['-f',
  '/run/user/1000/jupyter/kernel-a6504c0c-bed2-4405-8704-c008f52dcba6.json'])

That extra stuff that your parser can't handle is put in the extras list.

Run with a custom argv list works:

parser.parse_args(['-n', 'foobar'])
Namespace(name='foobar')

It's a good idea to put argparse code (at least the parse_args line) in a __main__ block, so it is not run when the script is imported. It will still run when the script is run as a script.

if __name__ == '__main__':
    import argparse

    parser = argparse.ArgumentParser(description='Foo')
    parser.add_argument('--name', '-n', default='foo', help='foo')

    args = parser.parse_args()
    print(args)

This script also works when using %run stack50763033.py. You can even give it arguments as you would with a script:

%run stack50763033.py -n testing

I have no idea what code is producing the level keyword error. You'll have to give us the traceback if you want help with that.

Upvotes: 0

Alan
Alan

Reputation: 3042

Ipython is running some command-line arguments in the background. This interfers with argparse and optparse.

See this bug for Spyder (Ipython IDE), where -f was being added as a command option and crashing as there was no handler for -f.

You could try checking the arguments currently in play (as they did for the Spyder bug) and putting a dummy handler in place.

Run

import sys
print(sys.argv)

inside Ipython and see what it outputs.

On my system, it gives

['/usr/lib/python3.6/site-packages/ipykernel_launcher.py', '-f', '/run/user/1000/jupyter/kernel-7537e4dd-b5e2-407c-9d4c-7023575cfc7c.json']

Argparse assumes the first entry is the program name (sys.argv[0]). In order to fix this, I had to call

parser = argparse.ArgumentParser(prog='myprogram', description='Foo')

... and now argparse works in my notebook.

Upvotes: 2

user45893
user45893

Reputation: 733

One solution is to parse an empty list of arguments:

import argparse

parser = argparse.ArgumentParser(description='Foo')
parser.add_argument('--name', '-n', default='foo', help='foo')

args = parser.parse_args([])

Another is to use parse_known_args:

args, _ = parser.parse_known_args()

Upvotes: 7

Related Questions