python 多线程日志管理
同一个日志文件, 但是区分线程:
import logging
import threading
# 配置日志
logging.basicConfig(
filename='thread_log.log',
filemode='a',
format='%(asctime)s - %(threadName)s - %(levelname)s - %(message)s',
level=logging.DEBUG
)
# 定义一个线程函数
def worker():
logging.debug('Worker thread started')
logging.info('Performing some work')
logging.warning('Warning: Something might go wrong')
logging.error('Error occurred')
logging.critical('Critical error detected')
# 创建线程
threads = []
for i in range(5):
t = threading.Thread(target=worker, name=f'Thread-{i}')
threads.append(t)
t.start()
# 等待所有线程完成
for t in threads:
t.join()
多线程, 每个线程有自己独立的日志文件和保存地址 (线程内部定义)
import threading
import logging
import time
import os
# 创建一个线程类,每个线程有自己的日志文件路径
class WorkerThread(threading.Thread):
def __init__(self, name, log_path):
super().__init__(name=name)
self.log_path = log_path
self.logger = self._setup_logger()
def _setup_logger(self):
# 创建 logger
logger = logging.getLogger(self.name)
logger.setLevel(logging.DEBUG)
# 创建文件处理器
fh = logging.FileHandler(self.log_path)
fh.setLevel(logging.DEBUG)
# 创建格式器并添加到处理器
formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
fh.setFormatter(formatter)
# 添加处理器到 logger
logger.addHandler(fh)
return logger
def run(self):
for i in range(5):
self.logger.info(f"Thread {self.name} logging iteration {i}")
time.sleep(1)
# 创建不同的日志路径(可以是不同目录)
log_paths = {
"Thread-A": os.path.join("logs_a", "thread_a.log"),
"Thread-B": os.path.join("logs_b", "thread_b.log"),
"Thread-C": os.path.join("logs_c", "thread_c.log"),
}
# 确保日志目录存在
for path in log_paths.values():
os.makedirs(os.path.dirname(path), exist_ok=True)
# 创建并启动线程
threads = []
for name, path in log_paths.items():
t = WorkerThread(name, path)
threads.append(t)
t.start()
# 等待所有线程完成
for t in threads:
t.join()
print("所有线程完成,日志已写入各自文件。")
主线程定义好日志器传递到线程里使用
import threading
import logging
import time
import os
# 定义线程类,接收外部传入的 logger
class WorkerThread(threading.Thread):
def __init__(self, name, logger):
super().__init__(name=name)
self.logger = logger
def run(self):
for i in range(5):
self.logger.info(f"{self.name} logging iteration {i}")
time.sleep(1)
# 在主线程中创建日志器
def create_logger(name, log_path):
logger = logging.getLogger(name)
logger.setLevel(logging.DEBUG)
# 避免重复添加 handler
if not logger.handlers:
os.makedirs(os.path.dirname(log_path), exist_ok=True)
fh = logging.FileHandler(log_path)
fh.setLevel(logging.DEBUG)
formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
fh.setFormatter(formatter)
logger.addHandler(fh)
return logger
# 定义每个线程的日志路径
log_paths = {
"Thread-A": "logs_a/thread_a.log",
"Thread-B": "logs_b/thread_b.log",
"Thread-C": "logs_c/thread_c.log",
}
# 创建 logger 并启动线程
threads = []
for name, path in log_paths.items():
logger = create_logger(name, path)
thread = WorkerThread(name, logger)
threads.append(thread)
thread.start()
# 等待所有线程完成
for t in threads:
t.join()
print("所有线程完成,日志已写入各自文件。")
主线程定义日志器, 并且不传递参数. 在线程内部直接使用
import threading
import logging
import os
import time
# 在主线程中配置多个日志器
def setup_loggers(log_config):
for name, path in log_config.items():
logger = logging.getLogger(name)
logger.setLevel(logging.DEBUG)
# 避免重复添加 handler
if not logger.handlers:
os.makedirs(os.path.dirname(path), exist_ok=True)
fh = logging.FileHandler(path)
fh.setLevel(logging.DEBUG)
formatter = logging.Formatter('%(asctime)s - %(threadName)s - %(levelname)s - %(message)s')
fh.setFormatter(formatter)
logger.addHandler(fh)
# 子线程中直接获取自己的 logger
def worker(logger_name):
logger = logging.getLogger(logger_name)
for i in range(3):
logger.info(f"Logging from {logger_name}, iteration {i}")
time.sleep(1)
# 每个线程的日志路径配置
log_config = {
"Thread-A": "logs/thread_a/thread_a.log",
"Thread-B": "logs/thread_b/thread_b.log",
"Thread-C": "logs/thread_c/thread_c.log",
}
# 主线程配置所有日志器
setup_loggers(log_config)
# 启动线程,每个线程使用自己的 logger 名称
threads = []
for name in log_config.keys():
t = threading.Thread(target=worker, name=name, args=(name,))
threads.append(t)
t.start()
for t in threads:
t.join()
print("✅ 所有线程完成,日志已分别写入各自文件。")
如果线程调用了其他程序, 但是又希望被调用的程序日志也写到这个线程里头, 建议用线程ID作为name比如,
import logging
import threading
def do_something():
logger = logging.getLogger(threading.current_thread().name)
logger.info("This log goes to the current thread's logger")
浙公网安备 33010602011771号