• Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 921
  • Last Modified:

Python - command Line how to Args

Hi,

from the commend line I need to execute a file liek this.

test.py daily [YYY-WW-DD-HH]

the date time stamp is optional

Is is the first time I am doing this.

What is the code to get this info?

If the time is optional then revert to current time e.g.

if input_time==None:
 time = now

0
dmontgom
Asked:
dmontgom
  • 3
  • 2
  • 2
  • +2
2 Solutions
 
sjklein42Commented:
http://diveintopython.org/scripts_and_streams/command_line_arguments.html

Each command-line argument passed to the program will be in sys.argv, which is just a list.

Put this in your program to see how the arguments are being passed in:

#argecho.py

import sys

for arg in sys.argv: 
    print arg

Open in new window

0
 
dmontgomAuthor Commented:
I am not looking for a link....looking for a solution.  I know how to google.

Here a better link

http://www.doughellmann.com/PyMOTW/getopt/

I am looking for best pratice for handing the case where the second optinal is optional.
0
 
dmontgomAuthor Commented:
THis is what I did...but I know its not proper.  What is best practice?

 #job-name = daily | hourly
    if sys.argv[1:][0]=='daily':
        job_type='daily'
    elif sys.argv[1:][0]=='hourly':
        job_type='hourly'
    else:
        print 'job name not specified'
        exit()
       
    #YYYY-MM-DD-HH
    try:
        dt_flag = sys.argv[1:][1]
        if len(dt_flag)!=13:
            print 'date is not in proper format'
            exit()
        now_utc = datetime.datetime.fromtimestamp(time.mktime(time.strptime(dt_flag, "%Y-%m-%d-%H")))
    except:
        now_utc = datetime.datetime.now(timezone('UTC'))
0
Get expert help—faster!

Need expert help—fast? Use the Help Bell for personalized assistance getting answers to your important questions.

 
LunarNRGCommented:
Best practice? Why didn't you say so? ;)

Although, I'm not sure you'll get consensus.  I tend to think that employing the argparse[1] module (now included in python 3.2) might be considered the best practice (also available as a 3rd party module for previous python versions). It has facilities for optional arguments.

You should really try to avoid using bare excepts, in favor of explicitly specifying the type of exception expected (the latter being the best practice). Otherwise, I don't think there is a whole lot wrong with your approach -- you can simplify it some, perhaps take greater advantage of exception handling. Something like (untested) ...

try:
    job_type, dt_flag = sys.argv[1:]
except ValueError:
    try:
        job_type = sys.argv[1:][0]
    except IndexError:
        print 'job name is a required argument'
        sys.exit(1)
    now_utc = datetime.datetime.now(timezone('UTC'))
else:
    if job_type.lower() not in ('hourly', 'daily'):
        print 'invalid job name'
        sys.exit(1)
    try:
        now_utc = datetime.datetime.fromtimestamp(time.mktime(time.strptime(dt_flag, "%Y-%m-%d-%H")))
    except ValueError:
        print 'date is not in proper format'
        sys.exit(1)

Open in new window


[1] http://docs.python.org/dev/library/argparse.html

HTH
0
 
LunarNRGCommented:
FWIW, here an example using argparse (also untested) ...

import argparse

def datify(s):
    try:
        return datetime.datetime.fromtimestamp(time.mktime(time.strptime(s, "%Y-%m-%d-%H")))
    except ValueError:
        raise argparse.ArgumentTypeError('date is not in proper format')

parser = argparse.ArgumentParser()
parser.add_argument('jobtype', choices=['hourly', 'daily'])
parser.add_argument('nowutc', type=datify)

args = parser.parse_args()

print args.jobtype
print args.nowutc

Open in new window


0
 
peprCommented:
I suggest to start with as simple as possible approach and enhance it later. Try the code below:

a.py
import sys
import time

print sys.argv              # this is a Python list data type

if len(sys.argv) < 2:       # sys.argv[0] is the name of a program/script
    print 'Expecting at least one argument.'
    sys.exit(1)             # terminate immediately
    
frequency = sys.argv[1]     # 'daily' or whatever -- you should test it
theTime = time.localtime()  # default, now

if len(sys.argv) > 2:       # the third argument present
    theTime = time.strptime(sys.argv[2], '%Y-%m-%d-%H')
    
print frequency
print theTime    

Open in new window


You can try to call it like this

C:\tmp\___python\dmontgom\Q_26892495>python a.py
['a.py']
Expecting at least one argument.

C:\tmp\___python\dmontgom\Q_26892495>python a.py daily
['a.py', 'daily']
daily
time.struct_time(tm_year=2011, tm_mon=3, tm_mday=17, tm_hour=10, tm_min=0, tm_sec=51, tm_wday=3, tm_yday=76, tm_isdst=0)

C:\tmp\___python\dmontgom\Q_26892495>python a.py daily 2011-03-11-10
['a.py', 'daily', '2011-03-11-10']
daily
time.struct_time(tm_year=2011, tm_mon=3, tm_mday=11, tm_hour=10, tm_min=0, tm_sec=0, tm_wday=4, tm_yday=70, tm_isdst=-1)

C:\tmp\___python\dmontgom\Q_26892495>python a.py daily cripledTS
['a.py', 'daily', 'cripledTS']
Traceback (most recent call last):
  File "a.py", line 14, in <module>
    theTime = time.strptime(sys.argv[2], '%Y-%m-%d-%H')
  File "c:\Python27\lib\_strptime.py", line 454, in _strptime_time
    return _strptime(data_string, format)[0]
  File "c:\Python27\lib\_strptime.py", line 325, in _strptime
    (data_string, format))
ValueError: time data 'cripledTS' does not match format '%Y-%m-%d-%H'

Open in new window


I am not sure if the format of the timestamp is what you really want (not clear from the question).

I suggest to add the try/except construct only when you are sure why -- see the last example.  Also, there is no need for datetime manipulation unless you want do do some calculation where working with the time structure is not enough.

A side note: I can see no reason for using expressions like sys.argv[1:][0].  This is simply sys.argv[1] only extracted by more complex way.
0
 
LunarNRGCommented:
There are potentially even more problems, but these few stood out to me after re-reading my posts -- and it's safe to assume both remain untested. I've also included a few notes, as comments in the code. Please ask questions, if you need additional clarification.

#!/usr/bin/env python
import sys, datetime
from pytz import timezone

# take only the first 2 arguments, if less than 2 check for one
try: 
    # this will ignore arguments after the 2nd
    job_type, dt_flag = sys.argv[1:3]
except ValueError:
    # take the first argument, exit if not given
    try: 
        # pepr is right about [1:][0] vs [1]
        job_type = sys.argv[1]
    except IndexError:
        print 'job name is a required argument'
        sys.exit(1)
    # default value for optional argument
    now_utc = datetime.datetime.now(timezone('UTC'))
else:
    # restrict choices of first argument
    if job_type not in ('hourly', 'daily'):
        print 'invalid job name'
        sys.exit(1)
    try:
        # datetime objects now have a strptime method, starting w/ python 2.5
        now_utc = datetime.datetime.strptime(dt_flag, "%Y-%m-%d-%H")
    except ValueError:
        print 'date is not in proper format'
        sys.exit(1)

Open in new window


Sample output:

$ ./args2.py 
job name is a required argument
$ ./args2.py daily
daily
2011-03-17 14:53:39.420964+00:00
$ ./args2.py daily 2011-01-01-01
daily
2011-01-01 01:00:00
$ ./args2.py daily 2011-01-01
date is not in proper format
$ ./args2.py monthly 2011-01-01-01
invalid job name

Open in new window


#!/usr/bin/env python
import argparse, datetime
from pytz import timezone

# argparse handles most of the drudgery of dealing with 
# command-line options and arguments, as you can see ...

# you can define your own "type" functions in argparse, very useful
def convert_to_date(strng):
    try:
        return datetime.datetime.strptime(strng, "%Y-%m-%d-%H")
    except ValueError:
        raise argparse.ArgumentTypeError('date is not in proper format')

parser = argparse.ArgumentParser()
parser.add_argument('jobtype', choices=['hourly', 'daily'], metavar='JOBTYPE', help='The job name.')
# default value, used when the 2nd arg is not passed
parser.add_argument(
    'nowutc', nargs='?', type=convert_to_date, metavar='TIMESTAMP',
    default=datetime.datetime.now(timezone('UTC')), help='Timestamp [optional]'
)

args = parser.parse_args()

print args.jobtype
print args.nowutc

Open in new window


Sample output:

$ ./args.py
usage: args.py [-h] JOBTYPE [TIMESTAMP]
args.py: error: too few arguments
$ ./args.py daily
daily
2011-03-17 14:53:35.128120+00:00
$ ./args.py daily 2011-01-01-01
daily
2011-01-01 01:00:00
$ ./args.py daily 2011-01-01
usage: args.py [-h] JOBTYPE [TIMESTAMP]
args.py: error: argument TIMESTAMP: date is not in proper format
$ ./args.py monthly 2011-01-01-01
usage: args.py [-h] JOBTYPE [TIMESTAMP]
args.py: error: argument JOBTYPE: invalid choice: 'monthly' (choose from 'hourly', 'daily')
$ ./args.py -h
usage: args.py [-h] JOBTYPE [TIMESTAMP]

positional arguments:
  JOBTYPE     The job name.
  TIMESTAMP   Timestamp [optional]

optional arguments:
  -h, --help  show this help message and exit

Open in new window

0
 
James MurrellProduct SpecialistCommented:
This question has been classified as abandoned and is closed as part of the Cleanup Program. See the recommendation for more details.
0

Featured Post

Free Tool: Subnet Calculator

The subnet calculator helps you design networks by taking an IP address and network mask and returning information such as network, broadcast address, and host range.

One of a set of tools we're offering as a way of saying thank you for being a part of the community.

  • 3
  • 2
  • 2
  • +2
Tackle projects and never again get stuck behind a technical roadblock.
Join Now