Python argparse:从参数创建timedelta对象?

sch*_*nic 4 python timedelta argparse

我试图用argparse一个参数转换成一个timedelta对象.我的程序读入用户提供的字符串,并将它们转换为各种datetime对象供以后使用.我不能让filter_length论证正确处理.我的代码:

import datetime
import time
import argparse

def mkdate(datestring):
    return datetime.datetime.strptime(datestring, '%Y-%m-%d').date()

def mktime(timestring):
    return datetime.datetime.strptime(timestring, '%I:%M%p').time()

def mkdelta(deltatuple):
    return datetime.timedelta(deltatuple)

parser = argparse.ArgumentParser()
parser.add_argument('start_date', type=mkdate, nargs=1)
parser.add_argument('start_time', type=mktime, nargs=1, )
parser.add_argument('filter_length', type=mkdelta, nargs=1, default=datetime.timedelta(1))#default filter length is 1 day.
Run Code Online (Sandbox Code Playgroud)

我运行该程序,传递1timedelta价值(我只希望它是一天):

> python program.py 2012-09-16 11:00am 1
Run Code Online (Sandbox Code Playgroud)

但是我收到以下错误:

>>> program.py: error: argument filter_length: invalid mkdelta value: '1'
Run Code Online (Sandbox Code Playgroud)

我不明白为什么价值无效.如果我自己调用mkdelta函数,就像这样:

mkdelta(1)
print mkdelta(1)
Run Code Online (Sandbox Code Playgroud)

它返回:

datetime.timedelta(1)
1 day, 0:00:00
Run Code Online (Sandbox Code Playgroud)

这正是我正在寻找的价值.有人可以帮我弄清楚如何正确使用这种转换argparse吗?

Han*_*hen 7

请注意'1'错误消息中的引号?您将字符串传递给mkdelta,而在测试代码中,您传递一个整数.


Mar*_*ers 5

您的函数不处理字符串参数,这是 argparse 处理它的内容;呼吁int()它:

def mkdelta(deltatuple):
    return datetime.timedelta(int(deltatuple))
Run Code Online (Sandbox Code Playgroud)

如果您需要支持多天,则必须找到一种方法将传入的参数解析为 timedelta 参数。

你可以,例如,支持dhms后缀表示天,小时,分钟或秒:

_units = dict(d=60*60*24, h=60*60, m=60, s=1)
def mkdelta(deltavalue):
    seconds = 0
    defaultunit = unit = _units['d']  # default to days
    value = ''
    for ch in list(str(deltavalue).strip()):
        if ch.isdigit():
            value += ch
            continue
        if ch in _units:
            unit = _units[ch]
            if value:
                seconds += unit * int(value)
                value = ''
                unit = defaultunit
            continue
        if ch in ' \t':
            # skip whitespace
            continue
        raise ValueError('Invalid time delta: %s' % deltavalue)
    if value:
        seconds = unit * int(value)
    return datetime.timedelta(seconds=seconds)
Run Code Online (Sandbox Code Playgroud)

现在你的mkdelta方法接受更完整的增量,甚至整数:

>>> mkdelta('1d')
datetime.timedelta(1)
>>> mkdelta('10s')
datetime.timedelta(0, 10)
>>> mkdelta('5d 10h 3m 10s')
datetime.timedelta(5, 36190)
>>> mkdelta(5)
datetime.timedelta(5)
>>> mkdelta('1')
datetime.timedelta(1)
Run Code Online (Sandbox Code Playgroud)

默认单位是天。