我正在尝试计算标记为On和Off之间的持续时间。
以下是一个字符串中两行的示例:
01/01/2015 7:30:10 a.m. Tag off : 16 Address Ave $1.00 $26.00
01/01/2015 7:40:17 a.m. Tag on : 127 Address St $27
目前我将忽略该地址并专注于计算持续时间。每行都有Tag Off信息和Tag On信息,我有大约60行(所以30对),它们都来自一个.txt文件。
从上面的示例中,持续时间为10分7秒。
这是我的代码:
def import_file(filename):
input_file = open(filename, 'r' )
file_contents = input_file.read()
input_file.close()
def strip():
contents = import_file("data.txt")
def duration_cal():
pass
那么剥离所有不必要信息并将有关On或Off的时间和日期放入字典或列表的最佳方法是什么? (计算开启和关闭之间的持续时间)
答案 0 :(得分:1)
到目前为止看起来你还没做过多大的研究,你只打开一个文件,你甚至不按推荐的方式去做,因为你正在创建一个函数来处理python有一种语言的东西结构。
然后,您不会从import_file()
返回文件的内容,因此strip()
始终会将contents
设置为无。实际上,从设计的角度来看,您的功能并不实用。
更好的方法是:
#!/usr/bin/env python3
import os, sys
def print_durations(durations):
# this is to print nicely the durations
pass
def calculate_durations(contents):
# this is where the fun shall be, see implementation below
pass
def main():
if len(sys.argv) != 2:
print("Usage: {} filename".format(sys.argv[0]))
sys.exit(1)
if not os.path.isfile(sys.argv[1]):
print("Error: {} should be an existing file!".format(sys.argv[1]))
sys.exit(2)
with open(sys.argv[1], 'r') as f:
durations = calculate_durations(f.readlines())
print_durations(durations)
if __name__ == "__main__":
main()
这是创建以文件名作为第一个参数的脚本的最简单方法。如果您想要更好的CLI工具,可能需要试用docopt
或argparse
。
现在让我们进入有趣的部分,即使你显然没有努力实际尝试来实现算法,这是一个足以真正标记你的问题的理由......但仅限于因为它很有趣,以下是我的看法:
为了获得你的行的有趣位,你可以弹出你的python CLI,并拆分你的字符串以获得相关的部分。如果它在各个方面都是一致的,那么你就不需要像疯狂的正则表达式这样的高级内容:
>>> line = '01/01/2015 7:30:10 a.m. Tag off : 16 Address Ave $1.00 $26.00'
>>> line.split(' : ')
['01/01/2015 7:30:10 a.m. Tag off','16 Address Ave $1.00 $26.00']
>>> line.split(' : ')[0]
'01/01/2015 7:30:10 a.m. Tag off'
>>> line.split(' : ')[0].split(' Tag ')
['01/01/2015 7:30:10 a.m.','off']
>>> timestr, status = line.split(' : ')[0].split(' Tag ')
>>> print(status)
off
>>> print(timestr)
01/01/2015 7:30:10 a.m.
现在你需要以一种可以计算delta的方式转换时间,但是由于python不理解a.m.
作为am / pm标记,你需要先转换它:
>>> timestr = timestr.replace('a.m.', 'AM')
>>> import datetime
>>> timestamp = datetime.datetime.strptime(timestr, "%d/%m/%Y %I:%M:%S %p")
>>> timestamp
datetime.datetime(2015, 1, 1, 7, 30, 10)
最后得到两个时间戳之间的差值,你只需要减去日期:
>>> timestamp2 = datetime.datetime.strptime(line.split(' : ')[0].split(' Tag ')[0].replace('a.m.', 'AM'), "%d/%m/%Y %I:%M:%S %p")
>>> timestamp2 - timestamp
datetime.timedelta(0, 607)
>>> print(timestamp2 - timestamp)
0:10:07
然后你去!这个函数的内容相同:
import datetime
def calculate_durations(contents):
last_stamp = None
durations = []
for line in contents:
# extract time and status from the line
timestr, status = line.split(' : ')[0].split(' Tag ')
# fix a.m./p.m. to be AM/PM
timestr = timestr.replace('a.m.', 'AM').replace('p.m.', 'PM')
# load the time as a python timestamp
timestamp = datetime.datetime.strptime(timestr, "%d/%m/%Y %I:%M:%S %p")
# if this is the first timestamp, store the status, and consider the timestamp to be zero
if last_stamp is None:
durations.append((datetime.timedelta(0), status))
# otherwise calculate the timestamp since last
else:
durations.append((timestamp-last_stamp, status))
# save timestamp for next line
last_stamp = timestamp
return durations
def print_durations(durations):
for stamp, status in durations:
print("{} for {}".format(status, stamp))
你可以复制它,在python命令行中测试它,它将输出:
>>> contents = [
... '01/01/2015 7:30:10 a.m. Tag off : 16 Address Ave $1.00 $26.00',
... '01/01/2015 7:40:17 a.m. Tag on : 127 Address St $27']
...
>>> print_durations(calculate_durations(contents))
off for 0:00:00
on for 0:10:07
或者将它作为脚本运行,如果你把它们放在一起:
% python3 myscript.py myfile.log
off for 0:00:00
on for 0:10:07
HTH