python線程類改變類變量的操作代碼
python線程類改變類變量
python線程類改變類變量
#!/usr/bin/python3 import threading,time class Rep2(threading.Thread): delay = 5 def __init(self): threading.Thread.__init__(self) #self.delay = delay pass @classmethod def get_delay(cls): print('cls_delay:',cls.delay) @classmethod def set_delay(cls,delay): cls.delay = delay def run(self): while True: time.sleep(1) print('run_delay:',self.delay) # #測試1 a = Rep2() # 需要調(diào)用線程類的start()方法而不是run()方法,調(diào)用run()方法類變量delay的值不會改變 a.start() print("test1,started") Rep2.get_delay() time.sleep(5) Rep2.delay = 2 Rep2.get_delay() time.sleep(5) Rep2.set_delay(222) Rep2.get_delay() ''' 運行結(jié)果1: test1,started cls_delay: 5 run_delay: 5 run_delay: 5 run_delay: 5 run_delay: 5 run_delay: 5 cls_delay: 2 run_delay: 2 run_delay: 2 run_delay: 2 run_delay: 2 cls_delay: 222 run_delay: 222 run_delay: 222 run_delay: 222 '''
import threading,time class Rep2(): delay = 5 def __init(self): pass #self.delay = delay @classmethod def get_delay(cls): print('cls_delay:',cls.delay) @classmethod def set_delay(cls,delay): cls.delay = delay def run(self): print('run_delay:',self.delay) a = Rep2() a.run() print("test2,started") Rep2.get_delay() time.sleep(5) Rep2.delay = 2 Rep2.get_delay() time.sleep(5) Rep2.set_delay(222) Rep2.get_delay() a.run() ''' run_delay: 5 test2,started cls_delay: 5 cls_delay: 2 cls_delay: 222 run_delay: 222 '''
擴展
python使用標(biāo)準(zhǔn)庫logging實現(xiàn)多進(jìn)程安全的日志模塊
前言
原本應(yīng)用的日志是全部輸出到os的stdout,也就是控制臺輸出。因其它團隊要求也要保留日志文件,便于他們用其他工具統(tǒng)一采集,另一方面還要保留控制臺輸出,便于出問題的時候自己直接看pod日志。具體需求如下:
- 日志支持同時控制臺輸出和文件輸出
- 控制臺的輸出級別可以高點,比如WARNING,個人這邊的實際情況是WARNING或ERROR就能判斷大部分問題。日志文件的輸出級別設(shè)置為INFO,如果控制臺日志找不到問題,可以具體看日志文件的內(nèi)容。
- 因為用到了多進(jìn)程,所以寫文件的時候要保證多進(jìn)程安全,避免日志內(nèi)容不會缺失。
- 日志文件可以設(shè)置自動分割,避免長時間不清理導(dǎo)致硬盤存儲資源浪費。
因為不允許隨便使用第三方包,所以只能用標(biāo)準(zhǔn)庫的logging。一開始想的方法比較挫——對文件加鎖,但改來改去發(fā)現(xiàn)根本不能給別人review。翻python官方文檔的時候發(fā)現(xiàn)logging庫有個QueueHandler
和QueueListener
,簡單試了下感覺邏輯還算清楚,遂簡單整理了下代碼。
示例代碼
目錄結(jié)構(gòu)如下,main.py是入口腳本,logs目錄和app.log將有程序運行時自動生成,主要日志功能放在pkg/log.py
文件中。pkg/__init__.py
為空文件,僅用于標(biāo)識為python包。
. ├── main.py ├── logs │ └── app.log └── pkg ├── __init__.py └── log.py
pkg/log.py
內(nèi)容如下,主要提供logger
已經(jīng)配置好的日志對象,該對象先將日志記錄到QueueHandler,然后QueueListener從隊列中取日志,并分別輸出到控制臺和日志文件中。close_log_queue()
方法將在主進(jìn)程結(jié)束時調(diào)用。
import logging from logging.handlers import TimedRotatingFileHandler, QueueHandler, QueueListener import sys import os # from queue import Queue from multiprocessing import Queue log_queue = Queue(-1) queue_listener = "" logdir = "logs" logfile = f"{logdir}/app.log" if not os.path.exists(logdir): os.makedirs(logdir, exist_ok=True) def set_formatter(): """設(shè)置日志格式化器""" fmt = "%(asctime)s | %(levelname)s | %(name)s | %(filename)s:%(lineno)d | %(funcName)s | %(message)s" datefmt = "%Y-%m-%d %H:%M:%S" return logging.Formatter(fmt, datefmt=datefmt) def set_queue_handler(): # 不要給QueueHandler重復(fù)設(shè)置formatter, 會引起重復(fù)嵌套 handler = QueueHandler(log_queue) handler.setLevel(logging.INFO) return handler def set_stream_handler(formatter: logging.Formatter): # 輸出到控制臺的日志處理器 handler = logging.StreamHandler(sys.stdout) handler.setLevel(logging.WARNING) handler.setFormatter(formatter) return handler def set_timed_rotating_file_handler(formatter: logging.Formatter): # 輸出到文件的日志處理器, 每天生成一個新文件, 最多保留10個文件 handler = TimedRotatingFileHandler(logfile, when="midnight", backupCount=10, encoding="utf-8") handler.setLevel(logging.INFO) handler.setFormatter(formatter) return handler def close_log_queue(): # 關(guān)閉隊列監(jiān)聽器 global queue_listener if queue_listener: queue_listener.stop() def get_logger(name: str = "mylogger", level: int = logging.INFO): logger = logging.getLogger(name) logger.setLevel(level) formatter = set_formatter() stream_handler = set_stream_handler(formatter) file_handler = set_timed_rotating_file_handler(formatter) queue_handler = set_queue_handler() logger.addHandler(queue_handler) global queue_listener if not queue_listener: queue_listener = QueueListener(log_queue, stream_handler, file_handler, respect_handler_level=True) queue_listener.start() return logger logger = get_logger() if __name__ == "__main__": logger.info("test") close_log_queue()
main.py
內(nèi)容如下,主要是創(chuàng)建子進(jìn)程調(diào)用logger,觀察日志輸出是否正常。
from multiprocessing import Process from pkg.log import logger, close_log_queue import os class MyProcess(Process): def __init__(self, delay): self.delay = delay super().__init__() def run(self): for i in range(self.delay): logger.info(f"pid: {os.getpid()}, {i}") if __name__ == '__main__': logger.info(f"main process pid: {os.getpid()}") for i in range(10): p = MyProcess(10000) p.start() p.join() logger.info("main process end") close_log_queue()
執(zhí)行輸出大致如下所示:
$ tail logs/app.log
2024-01-22 23:10:17 | INFO | mylogger | main.py:12 | run | pid: 7908, 1
2024-01-22 23:10:17 | INFO | mylogger | main.py:12 | run | pid: 7908, 2
2024-01-22 23:10:17 | INFO | mylogger | main.py:12 | run | pid: 7908, 3
2024-01-22 23:10:17 | INFO | mylogger | main.py:12 | run | pid: 7908, 4
2024-01-22 23:10:17 | INFO | mylogger | main.py:12 | run | pid: 7908, 5
2024-01-22 23:10:17 | INFO | mylogger | main.py:12 | run | pid: 7908, 6
2024-01-22 23:10:17 | INFO | mylogger | main.py:12 | run | pid: 7908, 7
2024-01-22 23:10:17 | INFO | mylogger | main.py:12 | run | pid: 7908, 8
2024-01-22 23:10:17 | INFO | mylogger | main.py:12 | run | pid: 7908, 9
2024-01-22 23:10:17 | INFO | mylogger | main.py:21 | <module> | main process end
補充
logging還內(nèi)置很多其它handler,比如按文件大小自動切割,日志通過HTTP請求輸出,日志輸出到syslog等,可按照自己需求進(jìn)行定制。
到此這篇關(guān)于python使用標(biāo)準(zhǔn)庫logging實現(xiàn)多進(jìn)程安全的日志模塊的文章就介紹到這了,更多相關(guān)python多進(jìn)程安全日志模塊內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
到此這篇關(guān)于python線程類改變類變量的文章就介紹到這了,更多相關(guān)python線程類改變類變量內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Keras 利用sklearn的ROC-AUC建立評價函數(shù)詳解
這篇文章主要介紹了Keras 利用sklearn的ROC-AUC建立評價函數(shù)詳解,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2020-06-06Python實現(xiàn)讀取文件夾按數(shù)字排序功能
這篇文章主要介紹了Python讀取文件夾按數(shù)字排序,代碼簡單易懂,對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2022-09-09pyppeteer執(zhí)行js繞過webdriver監(jiān)測方法上
這篇文章主要為大家介紹了pyppeteer執(zhí)行js繞過webdriver監(jiān)測方法,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步早日升職加薪2022-04-04