Question

Normally I run this script fro the command line with one argument: python myscript.py argument

But when this argument is lacking, I want the error message to be shown:

usage: myscript.py [file ...]

Script:

import sys
from lxml import etree

filename = sys.argv[1]

tree = etree.parse(filename)

def f1():
...
def main():
   if len(sys.argv) < 2:
           print 'usage: extract.py [file ...]'
           sys.exit(1)

   else:
      f1()

Before I had this working, I could the error message in case there is no argument, but now it stopped working, I don't see why... I only get this message when I run the script without the argument from the command line:

Traceback (most recent call last):
  File "myscript.py", line 14, in <module>
    filename = sys.argv[1]
IndexError: list index out of range
Was it helpful?

Solution

The line filename = sys.argv[1] runs first. Your len() test is not reached.

Move setting the filename and tree into the main() function, and don't use globals here:

def f1(tree):
    ...

def main():
    if len(sys.argv) < 2:
        print 'usage: extract.py [file ...]'
        sys.exit(1)

    filename = sys.argv[1]
    tree = etree.parse(filename)

    f1(tree)

if __name__ == '__main__':
    main()

OTHER TIPS

As Martijn says, sys.argv[1] gets referenced before you test len().

I prefer to move the tests into the calling clause instead of main, like so:

import sys
from lxml import etree

def f1(tree):
    pass

def main(filename):
    tree = etree.parse(filename)
    f1(tree)

if __name__=="__main__":
    if len(sys.argv) == 2:
        main(sys.argv[1])
    else:
        print 'usage: extract.py [file ...]'
        sys.exit(1)

I feel this provides a more logical division of responsibilities in the code.

rather than doing all this why not use argparse module from python. If the argument is not provided it will automatically print the usage statement as below

import argparse
parser = argparse.ArgumentParser()
parser.add_argument('file', type=argparse.FileType('r'))
args = parser.parse_args()      
print(args.file)

type=argparse.FileType('r') argument is not necessary but it is better to use.

'r' represents and checks whether the file is readable or exists.

Similarly you can use 'w' to check if file that you are passing is writable.

Output:

$> python progargs.py

usage: progargs.py [-h] file

progargs.py: error: too few arguments

$> python progargs.py testanotherprog.py

'testanotherprog.py', mode 'r' at 0x7fe8ee422270>

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top