Как сломать время l oop через несколько минут? - PullRequest
2 голосов
/ 24 марта 2020

У меня некоторое время l oop в моей программе python, и я хочу break из этого l oop через 5 минут, в настоящее время я использую следующий код:

start_time = time.time()
while time.time() - start_time < 300:
    # do something

Однако на каждую итерацию требуется дополнительное время для вычисления части time.time() - start_time < 300:. Например, если я использую for l oop с 30000 итерациями и длится 5 минут, приведенный выше код выполняет меньше итераций, чем этот.

Что мне с этим делать? Я должен сломать l oop через 5 минут, и я просто хочу справиться с этим по времени, а не for l oop итераций.

Один из моих друзей предложил datetime пакет, но я не знаю, как это работает.

Ответы [ 5 ]

0 голосов
/ 24 марта 2020

(немного повозившись позже, я думаю, что я в целом согласен с Аленом. Я получаю значительную скорость от простого прерывания после определенного числа итераций, но независимо от того, используется ли поток, time.time напрямую или частично подход выборки, в значительной степени все они в конечном итоге приводят к ухудшению времени l oop. time.time(), вероятно, уже достаточно высоко оптимизированы, поэтому все дополнительные логические значения и тому подобное, чтобы избежать его слишком частого использования, вероятно, не улучшат ничего).

Не знаю, является ли это более эффективным, но вы можете попробовать поток и общий изменяемый объект для управления l oop. Вот тест за 0,5 секунды.

import time
from threading import Thread

def myfunc(mutable_):
    time.sleep(0.5)
    mutable_.value = False
    print("done")


class Mutable:
    value = True

mutable_ = Mutable()

t = Thread(target=myfunc, args=(mutable_,))

start = time.time()
t.start()
while mutable_.value:
    print(time.time() - start)

Мне неизвестно, является ли атрибут l oop доступа к mutable_.value, который не требует непосредственного участия потока, настолько дешевле, чем опрос самого потока.

Теперь, в моем тесте, была небольшая разница, когда поток еще не обновил значение, поэтому l oop побежал немного по сравнению с использованием собственного локального проверка времени Может быть возможно установить время вашего потока на 299,9 секунды, приблизиться и более аккуратно финишировать sh.

Вот v2, использующий нить, спящий, чтобы получить большую часть пути (то есть 0,49), и a, обычно короткое замыкание time.time() проверка для завершения.

def myfunc(mutable_, looptime):
    time.sleep(looptime)
    mutable_.value = False

t = Thread(target=myfunc, args=(mutable_,.49))

t.start()
start = time.time()

while mutable_.value or (time.time() - start <= .5):
    print(time.time() - start)
0 голосов
/ 24 марта 2020

Я думаю, что использование потоков и сна - лучший подход. Вы можете сделать это простым способом, используя лямбда-функцию для создания спящего фонового потока и просто проверить, работает ли этот поток внутри вашего l oop (прервите l oop, когда время истечет):

from threading import Thread
from time import sleep

fiveMinutes = Thread(target=lambda:sleep(300)) # 5 min sleeping thread (300 seconds)
fiveMinutes.start() # start wait time

for i in range(10**10): # <-- this represents your loop condition
    # ...
    if not fiveMinutes.is_alive(): break # break after 5 minutes elapsed
    # ...

Это должно добавить меньше накладных расходов на вашу обработку l oop, поэтому итерации по тайм-ауту должны быть очень близки к эффективному времени для обработки того же количества итераций.

[ПРАВИТЬ ] Thread / sleep vs time.time ()

Я провел еще несколько тестов, и разница между использованием спящего потока и оптимальным использованием функции time () очень мала. Затраты составляют менее микросекунды за итерацию:

from time import time

fiveMinutes = time() + 300

for i in range(10**10): # <-- this represents your loop condition
    # ...
    if time() > fiveMinutes : break # break after 5 minutes elapsed
    # ...

Если вы получаете разницу в 3 секунды по выборке в 1 минуту, я подозреваю, что время обработки вашего logi c имеет собственную изменчивость (т.е. выполнение одного и того же количества итераций в al oop будет варьироваться от одного запуска к следующему). Либо это, либо вы проверяете время ожидания намного чаще, чем можно было бы предположить в 11 311 итерациях (возможно, проверяя внутри вложенного l oop). В моих тестах два подхода менялись менее чем на 0,5 секунды в течение 60-секундной выборки, выполняющей 41 000 итераций: + 0,37se c для time () и + 0,23se c для потока.

0 голосов
/ 24 марта 2020

Попробуйте следующее:

start_time = time.time() + 300
while True:
    if time.time() > start_time:
         break
0 голосов
/ 24 марта 2020

Звучит так, будто мне нужно реализовать тайм-аут. Вы можете использовать встроенный модуль threading, чтобы сделать это следующим образом:

import time
from threading import Thread, Event

stop = Event()

def function():
    while not stop.is_set():
        print('*')
        time.sleep(1)

thread = Thread(target=function)

thread.start()
thread.join(timeout=60)
stop.set()

Над кодом просто печатается * каждую секунду в течение 60 секунд.

0 голосов
/ 24 марта 2020

приведенный выше код выполняет меньше итераций, чем этот.

Вероятная причина в том, что проверка самого времени требует времени. Поэтому вы можете проверять время реже:

start_time = time.time()
lv = 0
while True:
    if lv == 100: # check time only once in 100 iterations
        if time.time() - start_time > 300:
            break
        else:
            lv = 0

    # do something

    lv +=1
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...