...
Just my blog

Blog about everything, mostly about tech stuff I made. Here is the list of stuff I'm using at my blog. Feel free to ask me about implementations.

Soft I recommend
Py lib I recommend

I'm using these libraries so you can ask me about them.

Python schedule how to

Задачка на вечер: Дано: задание, которое нужно выполнять в заданные промежутки времени, модуль Python schedule. Задача: запускать одну и ту же задачу с разными значениями offset раз в 10 сек, так, чтобы 0ffset=119 запускался в 10 сек от начала каждой минуты, offset=219 на 20й секунде каждой минуты и так далее. Все что пока смог сделать - заставить выполняться задачу каждую 10ю секунду, НО! это грозит тем, что каждые 10 сек в очередь добавляется каждая след. задача, так что может выполняться все куда чаще, чем раз в 10 сек. Есть идея - сделать задержку в 10 сек после каждого добавления задачи в очередь, тогда может получиться задержка в 20 сек, потом выполнение подряд нескольких задач, и снова 20 сек задержки. Сломал голову себе, сломаю и вам.

from time import strftime, sleep
import schedule


def del_comments_offset(offset):
    print("Func start")
    try:
        delete_comments_older(logFile, token, tk_owner_id, tk_group_id, tk_domain, offset)
    except:
        log_block("ERROR!!! : Connection error!")

offsets = [119,219,319,419,519,619,719,819,919,1019]
times = [10,20,30,40,50,60]
for offset in offsets:
    schedule.every(10).seconds.do(del_comments_offset, offset=offset)
    sleep(1)

# schedule.run_pending()

while True:
    schedule.run_pending()
    sleep(1)

Говнокодь @ Быстроотвечай

Вариант 1

Делаем счетчик временной паузы в цикле + 5, так после каждого выполнения скрипт будет ждать на 5 сек больше от прошлого выполнения. Задача будет выполняться таким образом, раз в каждые 5, 15, 25, 35, 45 и т.д. секунд, при этом никогда не будет возникать ситуация, когда в очереди накопится сразу несколько задач с интервалов в 1 сек! Ееее, велосипед!

def del_comments_offset(offset, sleep_time):
    start = time()
    print("Func start")
    try:
        delete_comments_older(logFile, token, tk_owner_id, tk_group_id, tk_domain, offset)
        sleep(sleep_time)
        end = time()
        print("Time spent: "+" "*6+str((end - start)))
    except:
        log_block("ERROR!!! : Connection error!")

offsets = [119,219,319,419,519,619]
sleeping = 0
for offset in offsets:
    schedule.every(10).seconds.do(del_comments_offset, offset=offset, sleep_time=sleeping)
    sleeping = sleeping + 10

while True:
    schedule.run_pending()
    sleep(1)

Лог выполнения:

C:\Python34\python.exe D:/Projects/PycharmProjects/depot/Work/vkontakte_tools/comments_delete/worker_comments_delete.py
Func start
delete_comments_older started: 23-07-2016 - 19:51:13
Offset: 19
Nothing to delete this time                        0
Bot Time spent:       6.58437705039978
Func time spent:       6.741384983062744
Func start
delete_comments_older started: 23-07-2016 - 19:51:30
Offset: 119
Nothing to delete this time                        0
Bot Time spent:       5.623322010040283
Func time spent:       15.626893997192383
Func start
delete_comments_older started: 23-07-2016 - 19:51:55
Offset: 220
Bot Time spent:       7.311417818069458
Func time spent:       27.313562154769897
Func start
delete_comments_older started: 23-07-2016 - 19:52:33
Offset: 321
Bot Time spent:       6.506373167037964
Func time spent:       36.51088190078735
Func start
delete_comments_older started: 23-07-2016 - 19:53:19
Offset: 422
Bot Time spent:       5.712325811386108
Func time spent:       45.71561312675476
Func start
delete_comments_older started: 23-07-2016 - 19:54:15
Offset: 523
Bot Time spent:       6.293359994888306
Func time spent:       56.29761600494385
Func start
delete_comments_older started: 23-07-2016 - 19:55:21
Offset: 624
Bot Time spent:       5.933340072631836
Func time spent:       65.93777203559875
Func start
delete_comments_older started: 23-07-2016 - 19:56:37
Offset: 725
Bot Time spent:       6.20735502243042
Func time spent:       76.21135902404785
Func start
delete_comments_older started: 23-07-2016 - 19:58:03
Offset: 826
Bot Time spent:       6.1743528842926025
Func time spent:       86.17792797088623
Func start
delete_comments_older started: 23-07-2016 - 19:59:40
Offset: 927
Bot Time spent:       7.393422842025757
Func time spent:       97.39816999435425
Func start
delete_comments_older started: 23-07-2016 - 20:01:27
Offset: 1028
Bot Time spent:       7.303418159484863
Func time spent:       107.30813789367676
Func start
delete_comments_older started: 23-07-2016 - 20:01:35
Offset: 19
Nothing to delete this time                        0
Bot Time spent:       6.035346031188965
Func time spent:       6.039345979690552
Func start
delete_comments_older started: 23-07-2016 - 20:01:51
Offset: 119
Nothing to delete this time                        0
Bot Time spent:       5.772330045700073
Func time spent:       15.776902198791504
Func start
delete_comments_older started: 23-07-2016 - 20:02:17
Offset: 220
Bot Time spent:       7.519429922103882
Func time spent:       27.522573947906494
Func start

Process finished with exit code -1

Вариант 2

Задать кроме того, таким же образом значение every в моменте добавления функции в очередь. Плохая идея, начинается та самая неразбериха с беспорядочным выполнением функций, когда время одной наслаивается на время другой.

C:\Python34\python.exe D:/Projects/PycharmProjects/depot/Work/vkontakte_tools/comments_delete/worker_comments_delete.py
Func start
delete_comments_older started: 23-07-2016 - 19:05:54
Arguments are: typical_kirovohrad 119
Time spent:       5.26430082321167
Func start
delete_comments_older started: 23-07-2016 - 19:06:04
Arguments are: typical_kirovohrad 219
Time spent:       15.48288607597351
Func start
delete_comments_older started: 23-07-2016 - 19:06:21
Arguments are: typical_kirovohrad 119
Time spent:       4.481256008148193
Func start
delete_comments_older started: 23-07-2016 - 19:06:25
Arguments are: typical_kirovohrad 319
Time spent:       24.470399856567383
Func start
delete_comments_older started: 23-07-2016 - 19:06:51
Arguments are: typical_kirovohrad 419
Time spent:       34.438366174697876
Func start
delete_comments_older started: 23-07-2016 - 19:07:25
Arguments are: typical_kirovohrad 519

Вариант 3

Здесь может быть ваш вариант, который должен оказаться лучшим, по сравнению с велосипедами выше.

Вариант 4

Все это фигня дурная, ибо зачем добавлять в цикле задачу, которая сама по себе должна выполняться в цикле в 10 сек? Вот окончательный вариант без велосипеда:

def del_comments_offset(offset, sleep_time):
    print("Func start")
    start = time()
    try:
        sleep(sleep_time)
        delete_comments_older(logFile, token, tk_owner_id, tk_group_id, tk_domain, offset)
        end = time()
        print("Func time spent: "+" "*6+str((end - start)))
    except:
        log_block("ERROR!!! : Connection error!")

offsets = [19,119,220,321,422,523,624,725,826,927,1028]
sleeping = 0
for offset in offsets:
    del_comments_offset(offset=offset, sleep_time=sleeping)
    sleeping = sleeping + 10

Лог также работает как в варианте 1, но только не нагружает бредом модуль scheduled, который функционально для других целей вообще служит.

Func start
delete_comments_older started: 23-07-2016 - 21:19:03
Offset: 19
Nothing to delete this time                        0
Bot Time spent:       6.293816089630127
Func time spent:       6.712736129760742
Func start
delete_comments_older started: 23-07-2016 - 21:19:19
Offset: 119
Nothing to delete this time                        0
Bot Time spent:       6.146492004394531
Func time spent:       16.172499895095825
Func start
delete_comments_older started: 23-07-2016 - 21:19:45
Offset: 220
Bot Time spent:       7.482980966567993
Func time spent:       27.525964975357056
Func start
delete_comments_older started: 23-07-2016 - 21:20:23
Offset: 321
Bot Time spent:       6.262005805969238
Func time spent:       36.291008949279785
Func start
delete_comments_older started: 23-07-2016 - 21:21:09
Offset: 422
Bot Time spent:       5.882701873779297
Func time spent:       45.9157030582428
Func start
delete_comments_older started: 23-07-2016 - 21:22:05
Offset: 523
Bot Time spent:       6.098874807357788
Func time spent:       56.140875816345215

Но все равно это все херня, и сейчас я объясню почему:

  • во-первых, модуль scheduler выполняет все "джобы" строго по порядку-очереди, таким образом, пока выполняется "долгая" задача, которая занимает, например 5 минут времени, другая задача, которая выполняется каждые 30 сек - будет стоять в очереди, пока 5минтка не закончится, и потом выполнится столько раз, раз в 30 сек, сколько будет свободно до следующей "джобы" на 5 минут, все это создает задержки, которые в конце-концов из-за путаницы могут суммироваться и достигать часов;
  • во-вторых, если запустить несколько "джоб" параллельно, благо модуль это позволяет, можно попасть в ловушку Вконтакта, которая запрещает выполнять более 25 запросов (при условии использования vk execute) - за одну секунду, таким образом, две параллельные "джобы" будут конкурировать и блокировать друг-друга с периодичностью раз в 5 мин, что в итоге может просто-напросто вырубить одну из функций так, как будто бы она и не исполнялась, что равносильно первому варианту с очередью, в сухом остатке.

Что имеем на выходе? Нужен вариант, когда функция, которая выполняется раз в 30 сек, выполнялась как можно чаще, но в промежутках была возможность вставить части более долгой функции, например, короткая функция выполняется на 30-й секунде, завершает работу на 45й а с 45й до следующей 30й будет выполняться часть долгой функции. Ну или тот вариант, когда функция выполняется постепенно в разные промежутки: часть в 5 мин, часть в 10, 20, 30 и т.п. Так получится совместить выполнение быстрой функции, которая должна работать регулярно, и долгой функции, которая будет запускаться редко, и удалять комментарии "в глубь" то есть со сдвигом до тысячных постов. И конечный вариант, конечно просто собрать все комменты, а потом запускать проверку на каждый, но это не вариант, снова проблема параллельных запросов и превышения кол-ва в сек.