2015-05-19 35 views
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 line)的一個線程。 – 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