0

I have a python script like this:

#I'm treating with text files
input = str(raw_input('Name1: '))
output = str(raw_input('Name2: '))

inputFile = open(input, 'r')
outputFile = open(output, 'w')

def doSomething():

    #read some lines of the input
    #write some lines to the output file

inputFile.close()
outputFile.close()

So, you have to put the name of the input file and the name of the output after you call the script in a shell:

python script.py

But I wonder if it's possible to call directly the input file and set the name of the output file by the time I'm calling the script, so the syntax of the calling will be something like:

python script.py inputFile.txt outputFile.txt

Then, it makes the same than the other, but without using the raw_input method. How can I make this?

arnaugamez
  • 23
  • 7

2 Answers2

4

You can use sys.argv:

The list of command line arguments passed to a Python script. argv[0] is the script name (it is operating system dependent whether this is a full pathname or not). If the command was executed using the -c command line option to the interpreter, argv[0] is set to the string '-c'. If no script name was passed to the Python interpreter, argv[0] is the empty string.

import sys

input_filename = sys.argv[1]
output_filename = sys.argv[2]

with open(input_filename, 'r') as input_file, open(output_filename, 'w') as output_file:
    # do smth

Also, instead of manually doing close() on files, use with context manager.

Also, for more complex handling of command-line arguments, consider using argparse module:

The argparse module makes it easy to write user-friendly command-line interfaces. The program defines what arguments it requires, and argparse will figure out how to parse those out of sys.argv. The argparse module also automatically generates help and usage messages and issues errors when users give the program invalid arguments.

alecxe
  • 462,703
  • 120
  • 1,088
  • 1,195
  • 4
    Best not to call it `input` - as you'll override the builtin `input` - and for Python 2.7 onwards, you can inline the with `with open(input_fname) as fin, open('output_fname', 'w') as fout`... – Jon Clements Sep 01 '13 at 12:30
  • 1
    @JonClements oh, sure, shadowing built-in. Thank you, haven't noticed. – alecxe Sep 01 '13 at 12:30
  • As long as you are here, you might as well put a check - otherwise there will be another ticket that I am getting this `IndexError` and I don't know why :) – Burhan Khalid Sep 01 '13 at 12:51
  • @BurhanKhalid good point, but how about leaving that as a homework? :) – alecxe Sep 01 '13 at 12:54
1

You can pass the input and output file names as arguments to the script. Here is a snippet of how to go about.

import sys

#check that the input and output files have been specified 
if len(sys.argv) < 3 :
   print 'Usage : myscript.py <input_file_name> <output_file_name>'
   sys.exit(0)

input_file = open(sys.argv[1])
output_file = open(sys.argv[2])
input_file.read()
output_file.write()
input_file.close()
output_file.close()

You now invoke the script as myscript.py inputfile.txt outputfile.txt

Note that you may want to check that the input and output file names have been specified before you open the the files and throw an error if not. Hence you can

Prahalad Deshpande
  • 4,709
  • 1
  • 20
  • 22
  • oh! no: [`with` statement](http://docs.python.org/2/reference/compound_stmts.html#the-with-statement). – Ashwini Chaudhary Sep 01 '13 at 12:28
  • You can use the with statment too. I just showed you a another way of doing it – Prahalad Deshpande Sep 01 '13 at 12:32
  • *There should be one-- and preferably only one --obvious way to do it.* -- Zen of python – Ashwini Chaudhary Sep 01 '13 at 12:37
  • :) Agreed. However, here the essence of the question was about how to pass filenames directly to the script without waiting for user input - hence the snipped without a **with**. I focused mainly on script parameter validation and it's usage. However, I agree with you - There should be one and preferably only one --obvious way to do it :) – Prahalad Deshpande Sep 01 '13 at 14:02