Python 记录失败,日志文件位于网络驱动器上 (windows 10)

Python logging failes with log-file on network drive (windows 10)

我想使用 python 的日志模块将日志记录到网络驱动器上的文件中。我的问题是日志记录在某个随机点失败,给我这个错误:

--- Logging error ---
Traceback (most recent call last):
  File "c:\programme\anaconda3\lib\logging\__init__.py", line 1085, in emit
    self.flush()
  File "c:\programme\anaconda3\lib\logging\__init__.py", line 1065, in flush
    self.stream.flush()
OSError: [Errno 22] Invalid argument
Call stack:
  File "log_test.py", line 67, in <module>
    logger_root.error('FLUSH!!!'+str(i))
Message: 'Minute:120'
Arguments: ()
--- Logging error ---
Traceback (most recent call last):
  File "c:\programme\anaconda3\lib\logging\__init__.py", line 1085, in emit
    self.flush()
  File "c:\programme\anaconda3\lib\logging\__init__.py", line 1065, in flush
    self.stream.flush()
OSError: [Errno 22] Invalid argument
Call stack:
  File "log_test.py", line 67, in <module>
    logger_root.error('FLUSH!!!'+str(i))
Message: 'FLUSH!!!120'
Arguments: ()

我在 Windows 10(版本 1909)的虚拟机上使用 Python 3.8.3 并记录 0.5.1.2。该脚本在存储日志文件的网络驱动器上的虚拟环境中运行。 我正在编写一个自动执行一些数据质量控制任务的脚本,我不是 100% 确定脚本将在何处(网络驱动器、本地驱动器等)结束,因此它应该能够在所有可能的情况下登录.该错误不会出现在脚本中的同一 position/line 处,而是随机出现。有时程序(总共约 120 分钟)完成时根本没有出现错误。

到目前为止我尝试了什么:

我相信日志文件在某个时候关闭了,因此无法向其中写入新的日志消息。我写了一个简单的脚本,基本上只做日志来检查它是否与我的原始脚本或日志记录过程本身有关。由于“only-logs-script”也随机失败,当网络驱动器上 运行 而不是我本地驱动器上的 运行 时,我假设它与网络连接有关驾驶。我考虑过将整个日志记录存储在内存中,然后写入文件,但 MemoryHandler 也会在脚本开头打开文件,因此有时会失败。

这是我的“only-logs-script”代码(log_test.py):

import logging
import logging.handlers
import os
import datetime
import time

##################################################################
# setting up a logger to create a log file with information about this programm
logfile_dir = 'logfiles_test'
CHECK_FOLDER = os.path.isdir(logfile_dir)

# if folder doesn't exist, create it
if not CHECK_FOLDER:
    os.makedirs(logfile_dir)
    print("created folder : ", logfile_dir)
log_path = '.\'+logfile_dir+'\'
Current_Date = datetime.datetime.today().strftime ('%Y-%m-%d_')
log_filename = log_path+Current_Date+'logtest.log'

print(log_filename)

# Create a root logger
logger_root = logging.getLogger()

# Create handlers
f1_handler = logging.FileHandler(log_filename, mode='w+')
f2_handler = logging.StreamHandler() 

f1_handler.setLevel(logging.INFO)
f2_handler.setLevel(logging.INFO)

# Create formatters and add it to handlers
f1_format = logging.Formatter('%(asctime)s | %(name)s | %(levelname)s | %(message)s \n')
f2_format = logging.Formatter('%(asctime)s | %(name)s | %(levelname)s | %(message)s \n')

f1_handler.setFormatter(f1_format)
f2_handler.setFormatter(f2_format)

# create a memory handler
memoryhandler = logging.handlers.MemoryHandler(
                    capacity=1024*100,
                    flushLevel=logging.ERROR,
                    target=f1_handler,
                    flushOnClose=True
                    )


# Add handlers to the logger
logger_root.addHandler(memoryhandler)
logger_root.addHandler(f2_handler)

logger_root.setLevel(logging.INFO)
logger_root.info('Log-File initiated.')

fname = log_path+'test.log'
open(fname, mode='w+')

for i in range(60*4):
    print(i)
    logger_root.warning('Minute:'+str(i))
    print('Write access:', os.access(fname, os.W_OK))
    if(i%10==0):
        logger_root.error('FLUSH!!!'+str(i))
    time.sleep(60)

是我的日志记录过程出现了严重错误还是因为网络驱动器?你们中有人对如何解决这个问题有任何想法吗?把全部信息存入内存,写入文件,最后能解决问题吗?我将如何最好地实现这一目标? 另一个想法是登录本地驱动器,然后在脚本完成后自动将文件复制到网络驱动器。非常感谢任何帮助,因为我已经尝试识别并解决这个问题好几天了。

谢谢!

因为这在 atm 上并没有真正实现,所以我将 post 我所做的“解决”我的问题。这不是一个令人满意的解决方案,因为它会在代码失败时失败,但总比根本不记录要好。 该解决方案的灵感来自于这个问题的答案:log messages to an array/list with logging

这就是我所做的:

import io

#####################################
# first create an in-memory file-like object to save the logs to
log_messages = io.StringIO()

# create a stream handler that saves the log messages to that object
s1_handler = logging.StreamHandler(log_messages)
s1_handler.setLevel(logging.INFO)

# create a file handler just in case
f1_handler = logging.FileHandler(log_filename, mode='w+')
f1_handler.setLevel(logging.INFO)

# set the format for the log messages
log_format = '%(asctime)s | %(name)s | %(levelname)s | %(message)s \n'
f1_format = logging.Formatter(log_format)
s1_handler.setFormatter(f1_format)
f1_format = logging.Formatter(log_format)

# add the handler to the logger
logger_root.addHandler(s1_handler)
logger_root.addHandler(f1_handler)

#####################################
# here would be the main code ...

#####################################
# at the end of my code I added this to write the in-memory-message to the file
contents = log_messages.getvalue()
# opening a file in 'w'
file = open(log_filename, 'w')
# write log message to file
file.write("{}\n".format(contents))
# closing the file and the in-memory object
file.close()
log_messages.close()

显然,当代码失败时,这会失败,但代码会尝试捕获大多数错误,所以我希望它能工作。我摆脱了内存处理程序,但保留了一个文件处理程序,以便在真正发生故障的情况下至少记录一些日志,直到文件处理程序失败。这远非理想,但对我的自动取款机有用。如果你有其他的 suggestions/improvements 我会很高兴听到他们!