7

引数をオブジェクト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ます (1 日だけにしたい):

> 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か?

4

5 に答える 5

7

'1'エラー メッセージ内の引用符に注目してください。mkdelta には文字列を渡しますが、テスト コードでは整数を渡します。

于 2012-09-17T15:07:13.883 に答える
6

関数は文字列引数を処理しません。これは 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)

デフォルトの単位は日です。

于 2012-09-17T15:06:04.463 に答える
2

カスタム アクションを使用して、残りのすべての引数を収集し、それらを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))
于 2012-09-17T17:14:34.617 に答える
0

この要点はあなたの問題を解決するようです: https://gist.github.com/jnothman/4057689

于 2014-02-11T10:30:27.973 に答える