[英]Python argparse: Create timedelta object from argument?
I am attempting to use argparse
to convert an argument into a timedelta
object.我正在尝试使用
argparse
将参数转换为timedelta
对象。 My program reads in strings supplied by the user and converts them to various datetime
objects for later usage.我的程序读取用户提供的字符串并将它们转换为各种
datetime
对象以供以后使用。 I cannot get the filter_length
argument to process correctly though.我无法正确处理
filter_length
参数。 My code:我的代码:
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.
I run the program, passing 1
as the timedelta
value (I only want it to be one day):我运行程序,传递
1
作为timedelta
值(我只希望它是一天):
> python program.py 2012-09-16 11:00am 1
But I get the following error:但我收到以下错误:
>>> program.py: error: argument filter_length: invalid mkdelta value: '1'
I don't understand why the value is invalid.我不明白为什么该值无效。 If I call the mkdelta function on its own, like this:
如果我自己调用 mkdelta 函数,如下所示:
mkdelta(1)
print mkdelta(1)
It returns:它返回:
datetime.timedelta(1)
1 day, 0:00:00
This is exactly the value that I'm looking for.这正是我正在寻找的价值。 Can someone help me figure out how to do this conversion properly using
argparse
?有人可以帮我弄清楚如何使用
argparse
正确进行这种转换吗?
Notice the quotes around '1'
in your error message?请注意错误消息中
'1'
周围的引号? You pass a string to mkdelta, whereas in your test code, you pass an integer.您将一个字符串传递给 mkdelta,而在您的测试代码中,您传递一个整数。
Your function doesn't handle a string argument, which is what argparse is handing it;您的函数不处理字符串参数,这是 argparse 处理它的内容; call
int()
on it:调用
int()
就可以了:
def mkdelta(deltatuple):
return datetime.timedelta(int(deltatuple))
If you need to support more than days, you'll have to find a way to parse the argument passed in into timedelta arguments.如果您需要支持多天,则必须找到一种方法将传入的参数解析为 timedelta 参数。
You could, for example, support d
, h
, m
or s
postfixes to denote days, hours, minutes or seconds:例如,您可以支持
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)
Now your mkdelta
method accepts more complete deltas, and even integers still:现在您的
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)
The default unit is days.默认单位是天。
You could use a custom action to collect all the remaining args and parse them into a timedelta
.您可以使用自定义操作来收集所有剩余的参数并将它们解析为
timedelta
。
This will allow you to write CLI commands such as这将允许您编写 CLI 命令,例如
% test.py 2012-09-16 11:00am 2 3 4 5
datetime.timedelta(2, 3, 5004) # args.filter_length
You could also provide optional arguments for --days
, --seconds
, etc, so you can write CLI commands such as您还可以为
--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))
这个要点似乎解决了你的问题: https : //gist.github.com/jnothman/4057689
Just in case somebody lands here looking to add a pandas.Timedelta
to an argument parser (as I just did), it turns out the following works just fine:以防万一有人想要将
pandas.Timedelta
添加到参数解析器(正如我刚刚所做的那样),结果证明以下工作正常:
parser = argparse.ArgumentParser()
parser.add_argument('--timeout', type=pd.Timedelta)
Then:然后:
>>> parser.parse_args(['--timeout', '24 hours'])
Namespace(timeout=Timedelta('1 days 00:00:00'))
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.