我正在尝试使用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.
我运行程序,将1
作为timedelta
值传递(我只希望它为一天):
> python program.py 2012-09-16 11:00am 1
但是我收到以下错误:
>>> program.py: error: argument filter_length: invalid mkdelta value: '1'
我不明白为什么价值无效。如果我自己调用mkdelta函数,就像这样:
mkdelta(1)
print mkdelta(1)
它返回:
datetime.timedelta(1)
1 day, 0:00:00
这正是我正在寻找的价值。有人可以帮助我弄清楚如何使用argparse
正确地进行转换吗?
答案 0 :(得分:7)
请注意错误消息中'1'
周围的引号?您将字符串传递给mkdelta,而在测试代码中,您传递一个整数。
答案 1 :(得分:4)
你的函数不处理字符串参数,这是argparse正在处理它的内容;在其上拨打int()
:
def mkdelta(deltatuple):
return datetime.timedelta(int(deltatuple))
如果你需要支持超过几天,你必须找到一种方法来解析传入timedelta参数的参数。
例如,您可以支持d
,h
,m
或s
后缀来表示天,小时,分钟或秒:
_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)
现在,您的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)
默认单位为天。
答案 2 :(得分:2)
您可以使用自定义操作收集所有剩余的args并将其解析为timedelta
。
这将允许您编写CLI命令,例如
% test.py 2012-09-16 11:00am 2 3 4 5
datetime.timedelta(2, 3, 5004) # args.filter_length
您还可以为--days
,--seconds
等提供可选参数,这样您就可以编写CLI命令,例如
% test.py 2012-09-16 11:00am --weeks 6 --days 0
datetime.timedelta(42) # args.filter_length
% test.py 2012-09-16 11:00am --weeks 6.5 --days 0
datetime.timedelta(45, 43200)
import datetime as dt
import argparse
def mkdate(datestring):
return dt.datetime.strptime(datestring, '%Y-%m-%d').date()
def mktime(timestring):
return dt.datetime.strptime(timestring, '%I:%M%p').time()
class TimeDeltaAction(argparse.Action):
def __call__(self, parser, args, values, option_string = None):
# print '{n} {v} {o}'.format(n = args, v = values, o = option_string)
setattr(args, self.dest, dt.timedelta(*map(float, values)))
parser = argparse.ArgumentParser()
parser.add_argument('start_date', type = mkdate)
parser.add_argument('start_time', type = mktime)
parser.add_argument('--days', type = float, default = 1)
parser.add_argument('--seconds', type = float, default = 0)
parser.add_argument('--microseconds', type = float, default = 0)
parser.add_argument('--milliseconds', type = float, default = 0)
parser.add_argument('--minutes', type = float, default = 0)
parser.add_argument('--hours', type = float, default = 0)
parser.add_argument('--weeks', type = float, default = 0)
parser.add_argument('filter_length', nargs = '*', action = TimeDeltaAction)
args = parser.parse_args()
if not args.filter_length:
args.filter_length = dt.timedelta(
args.days, args.seconds, args.microseconds, args.milliseconds,
args.minutes, args.hours, args.weeks)
print(repr(args.filter_length))
答案 3 :(得分:0)
这个要点似乎解决了你的问题:https://gist.github.com/jnothman/4057689
答案 4 :(得分:0)
以防万一有人想在参数解析器中添加 select a.*, r.country, r.tv_region
from all_data a left join
region r
on a.town = r.town;
(就像我刚做的那样),结果证明以下工作正常:
#div1 {
display: grid;
place-content: center;
}
---
#div1 {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
}
---
#div1 {
display: flex;
}
#div2 {
margin: auto;
}
---
#div1 {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}
那么:
pandas.Timedelta