2

Некоторое время борется с этим.Python 3 - Глобальные переменные с AsyncIO/APScheduler

Основываясь на этой теме: Using global variables in a function other than the one that created them

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

Код:

import asyncio 
from concurrent.futures import ProcessPoolExecutor 
from apscheduler.schedulers.asyncio import AsyncIOScheduler 
from datetime import datetime 
import time 


def day_limits(): 

     global variable 
     variable = 90 
     print ('Day Variable: ',variable) 

def night_limits(): 

     global variable 
     variable = 65 
     print ('Night Variable: ',variable) 


def thread_2(): 


    while True: 

     c_hour = int(datetime.now().strftime("%H")) 
     c_min = int(datetime.now().strftime("%M")) 
     c_sec = int(datetime.now().strftime("%S")) 

     print ('%02d:%02d:%02d - Variable: %d ' % (c_hour,c_min,c_sec,variable)) 

     time.sleep(2) 


if __name__ == "__main__": 

    variable = 60 

    scheduler = AsyncIOScheduler() 
    scheduler.add_job(day_limits, 'cron', hour=7,misfire_grace_time=3600,timezone='GB') 
    scheduler.add_job(night_limits, 'cron', hour=19, minute=32,misfire_grace_time=3600,timezone='GB') 
    scheduler.start() 

    scheduler.print_jobs() 

    executor = ProcessPoolExecutor(1) 
    loop = asyncio.get_event_loop() 
    baa = asyncio.async(loop.run_in_executor(executor, thread_2)) 


    try: 
     loop.run_forever() 

    except (KeyboardInterrupt, Exception): 
     loop.stop() 
     scheduler.shutdown() 

Результаты в:

19:31:54 - Variable: 60 
19:31:56 - Variable: 60 
19:31:58 - Variable: 60  
Night Variable: 65 
19:32:00 - Variable: 60 
19:32:02 - Variable: 60 

Я что-то не хватает, но я не могу видеть, что!

Мысли?

Спасибо !!!

+0

Это ваш полный фрагмент кода? Не понимаете, где вызываются функции? – shongololo

+0

В нижней части главной области. Два вызываются через APscheduler и работают корректно. Конечной вещью является нить asyncio (линия baa). – LikesAChallenge

ответ

1

Поскольку вы используете ProcessPoolExecutor, вам нужно использовать объект, безопасный для процесса, вместо обычного целого. Если вам нужно только поддерживать Linux (и поэтому может рассчитывать на наличие fork()), вы можете просто использовать обычный, глобальный multiprocessing.Value, чтобы сделать это.

import asyncio 
import multiprocessing 
from concurrent.futures import ProcessPoolExecutor 
from apscheduler.schedulers.asyncio import AsyncIOScheduler 
from datetime import datetime 
import time 


def day_limits(): 
     variable.value = 90 
     print ('Day Variable: ',variable.value) 

def night_limits(): 
     variable.value = 65 
     print ('Night Variable: ',variable.value) 


def thread_2(): 
    while True: 
     c_hour = int(datetime.now().strftime("%H")) 
     c_min = int(datetime.now().strftime("%M")) 
     c_sec = int(datetime.now().strftime("%S")) 

     print ('%02d:%02d:%02d - Variable: %d ' % (c_hour,c_min,c_sec,variable.value)) 

     time.sleep(2) 


if __name__ == "__main__": 
    variable = multiprocessing.Value('i', 60) 

    scheduler = AsyncIOScheduler() 
    scheduler.add_job(day_limits, 'cron', hour=7,misfire_grace_time=3600,timezone='GB') 
    scheduler.add_job(night_limits, 'cron', hour=19, minute=32,misfire_grace_time=3600,timezone='GB') 
    scheduler.start() 

    scheduler.print_jobs() 

    executor = ProcessPoolExecutor(1) 
    loop = asyncio.get_event_loop() 
    baa = asyncio.async(loop.run_in_executor(executor, thread_2)) 


    try: 
     loop.run_forever() 

    except (KeyboardInterrupt, Exception): 
     loop.stop() 
     scheduler.shutdown() 

Если вам необходимо поддерживать как Windows, и Linux, вам нужно использовать multiprocessing.Manager для создания Value объекта, и явно передать этот объект в функцию вы работаете в Executor:

import asyncio 
import multiprocessing 
from concurrent.futures import ProcessPoolExecutor 
from apscheduler.schedulers.asyncio import AsyncIOScheduler 
from datetime import datetime 
import time 


def day_limits(): 
     variable.value = 90 
     print ('Day Variable: ',variable.value) 

def night_limits(): 
     variable.value = 65 
     print ('Night Variable: ',variable.value) 


def thread_2(variable): 
    while True: 
     c_hour = int(datetime.now().strftime("%H")) 
     c_min = int(datetime.now().strftime("%M")) 
     c_sec = int(datetime.now().strftime("%S")) 

     print ('%02d:%02d:%02d - Variable: %d ' % (c_hour,c_min,c_sec,variable.value)) 

     time.sleep(2) 


if __name__ == "__main__": 

    m = multiprocessing.Manager() 
    variable = m.Value('i', 60) 

    scheduler = AsyncIOScheduler() 
    scheduler.add_job(day_limits, 'cron', hour=7,misfire_grace_time=3600,timezone='GB') 
    scheduler.add_job(night_limits, 'cron', hour=19, minute=32,misfire_grace_time=3600,timezone='GB') 
    scheduler.start() 

    scheduler.print_jobs() 

    executor = ProcessPoolExecutor(1) 
    loop = asyncio.get_event_loop() 
    baa = asyncio.async(loop.run_in_executor(executor, thread_2, variable)) # Need to pass variable explicitly 

    try: 
     loop.run_forever() 

    except (KeyboardInterrupt, Exception): 
     loop.stop() 
     scheduler.shutdown() 

Поскольку Windows не имеет поддержки fork, вам необходимо явно передать Value функции, которую вы используете в Executor. Если вы этого не сделаете, дочерний процесс скажет, что переменная не существует. Однако, поскольку вы явно передаете Value методу run_in_executor, вы не можете использовать обычный multiprocessing.Value - вы получите сообщение RuntimeError, в котором говорится, что «Синхронизированные объекты должны делиться только между процессами через наследование».

Использование multiprocessing.Manager работ вокруг этого; multiprocessing.Manager запускает процесс, который может создавать и управлять объектами, совместно использующими процессы. Вызов m.Value() возвращает Proxy к общему Value и что Proxy может быть отправлен в run_in_executor без привлечения исключения.

2

Проблема проста: вы используете ProcessPoolExecutor. Таким образом, задания выполняются в другом процессе, который имеет собственное пространство памяти. variable установлен правильно, но в родительском процессе он имеет другое значение (60), которое никогда не изменяется.

+0

Я думал, что это, вероятно, было из-за этого. Каково решение? Какой-то указатель? – LikesAChallenge

Смежные вопросы