Python使用basicConfig和RotatingFileHandler做日志轮转报WindowsError32怎么办
问题根源
你代码中对同一个日志文件C:\temp\debug.log注册了两个持有文件锁的日志处理器:
- 调用
logging.basicConfig时,会自动给根日志器添加一个默认的FileHandler,一直占用着debug.log的文件句柄 - 后续你又给自定义的
Rotating Log日志器添加了RotatingFileHandler,也打开了同一个文件
Windows系统下文件默认是独占访问模式,当RotatingFileHandler触发日志轮转需要重命名当前日志文件时,另一个FileHandler还在持有文件锁,就会抛出Error 32报错。
解决方案
两种修改方式选其一即可:
方式1:不要同时使用basicConfig的filename参数和自定义RotatingFileHandler
把日志格式、日志级别直接配置到你自定义的RotatingFileHandler上,删掉make_log_setup里logging.basicConfig的filename配置,改为单独创建格式器给轮转处理器用:
def make_log_setup(): global log_formatter date_strftime_format = "%d-%b-%y %H:%M:%S" message_format='%(asctime)s %(levelname)s %(module)s - %(funcName)s: %(message)s' # 提前创建格式器,后续给RotatingFileHandler使用 log_formatter = logging.Formatter(message_format, datefmt=date_strftime_format) # 只配置全局日志级别,不要指定filename,避免自动生成FileHandler占用文件 logging.basicConfig(level=logging.DEBUG) def create_rotating_log(path): logger = logging.getLogger("Rotating Log") # 关闭日志向上传递到根日志器,避免重复输出日志 logger.propagate = False logger.setLevel(logging.DEBUG) handler = RotatingFileHandler(path, maxBytes=20, backupCount=5) # 给轮转处理器绑定自定义日志格式 handler.setFormatter(log_formatter) logger.addHandler(handler) for i in range(6): logger.info("This is test log line %s" % i) time.sleep(1.5)
方式2:移除根日志器默认生成的FileHandler
如果要保留basicConfig的原有配置,就在添加RotatingFileHandler前先把根日志器上绑定的FileHandler关闭并移除:
def create_rotating_log(path): # 先清理根日志器占用目标文件的处理器 root_logger = logging.getLogger() for handler in root_logger.handlers[:]: if isinstance(handler, logging.FileHandler) and handler.baseFilename == path: handler.close() root_logger.removeHandler(handler) logger = logging.getLogger("Rotating Log") logger.setLevel(logging.DEBUG) # 后续原有逻辑保持不变 handler = RotatingFileHandler(path, maxBytes=20,backupCount=5) logger.addHandler(handler) for i in range(6): logger.info("This is test log line %s" % i) time.sleep(1.5)
小提示:你当前设置的maxBytes=20表示日志文件满20字节就触发轮转,仅适合测试用,实际使用时可以根据需求调整为更大的数值,比如10*1024*1024对应10MB。
内容的提问来源于stack exchange,提问作者Cheppy
相关产品推荐
相关产品推荐

