20

I am having an issue with the following section of Python code:

# Open/Create the output file
with open(sys.argv[1] + '/Concatenated.csv', 'w+') as outfile:

    try:
        with open(sys.argv[1] + '/MatrixHeader.csv') as headerfile:
            for line in headerfile:
                outfile.write(line + '\n')
    except:
        print 'No Header File'

Specifically the error is as follows:

Traceback (most recent call last):
  File "ConcatenateFiles.py", line 12, in <module>
    with open(sys.argv[1] + 'Concatenated.csv', 'w+') as outfile:
IndexError: list index out of range

I've done some research and it seems that the sys.argv might require an argument at the command line when running the script, but I'm not sure what to add or what the issue might be! I've also searched the site, but all of the solutions I've found either have no comments and/or don't include the open function as mine does.

mkrieger1
  • 19,194
  • 5
  • 54
  • 65
DataGuy
  • 1,695
  • 4
  • 22
  • 38
  • 1
    It should be just `python ConcatenateFiles.py `. That is assuming you are doing an `import sys` first – brechmos Jul 29 '15 at 00:01
  • " it seems that the sys.argv might require an argument at the command line when running the script, but I'm not sure what to add or what the issue might be" Well, do you understand what the command line is? Do you understand what "argument" means here? – Karl Knechtel Aug 09 '22 at 08:25

3 Answers3

18

sys.argv represents the command line options you execute a script with.

sys.argv[0] is the name of the script you are running. All additional options are contained in sys.argv[1:].

You are attempting to open a file that uses sys.argv[1] (the first argument) as what looks to be the directory.

Try running something like this:

python ConcatenateFiles.py /tmp
Steve O'Driscoll
  • 426
  • 4
  • 11
  • This worked, soft of! Now I get 'No header File' – DataGuy Jul 29 '15 at 00:07
  • The second `open` statement you are calling does not specify an open mode. The default is to open the file as read-only which will fail if the file does not exist. You will need to change that to `with open(sys.argv[1] + '/MatrixHeader.csv', 'w') as headerfile:` – Steve O'Driscoll Jul 29 '15 at 00:08
12

sys.argv is the list of command line arguments passed to a Python script, where sys.argv[0] is the script name itself.

It is erroring out because you are not passing any commandline argument, and thus sys.argv has length 1 and so sys.argv[1] is out of bounds.

To "fix", just make sure to pass a commandline argument when you run the script, e.g.

python ConcatenateFiles.py /the/path/to/the/directory

However, you likely wanted to use some default directory so it will still work when you don't pass in a directory:

cur_dir = sys.argv[1] if len(sys.argv) > 1 else '.'

with open(cur_dir + '/Concatenated.csv', 'w+') as outfile:

    try:
        with open(cur_dir + '/MatrixHeader.csv') as headerfile:
            for line in headerfile:
                outfile.write(line + '\n')
    except:
        print 'No Header File'
lemonhead
  • 5,328
  • 1
  • 13
  • 25
  • `cur_dir = sys.argv[1] if len(sys.argv) > 1 else '.'` This is what I was looking for, and I found it. If you don't want to pass in an argument, you don't have to. Thanks @lemonhead – TheWalkingData Feb 21 '17 at 18:19
5

I've done some research and it seems that the sys.argv might require an argument at the command line when running the script

Not might, but definitely requires. That's the whole point of sys.argv, it contains the command line arguments. Like any python array, accesing non-existent element raises IndexError.

Although the code uses try/except to trap some errors, the offending statement occurs in the first line.

So the script needs a directory name, and you can test if there is one by looking at len(sys.argv) and comparing to 1+number_of_requirements. The argv always contains the script name plus any user supplied parameters, usually space delimited but the user can override the space-split through quoting. If the user does not supply the argument, your choices are supplying a default, prompting the user, or printing an exit error message.

To print an error and exit when the argument is missing, add this line before the first use of sys.argv:

if len(sys.argv)<2:
    print "Fatal: You forgot to include the directory name on the command line."
    print "Usage:  python %s <directoryname>" % sys.argv[0]
    sys.exit(1)

sys.argv[0] always contains the script name, and user inputs are placed in subsequent slots 1, 2, ...

see also:

Community
  • 1
  • 1
Paul
  • 26,170
  • 12
  • 85
  • 119