【问题标题】:Python logging failes with log-file on network drive (windows 10)Python 日志记录失败,网络驱动器上的日志文件(Windows 10)
【发布时间】:2021-03-20 01:41:27
【问题描述】:

我想使用 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% 确定脚本最终会在哪里(网络驱动器、本地驱动器等),所以它应该能够在所有可能的情况下登录.错误不会出现在脚本中的同一位置/行,而是随机出现。有时程序(总共约 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)

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

谢谢!

【问题讨论】:

  • 文件的完整路径听起来像是某种问题。尝试在路径中仅使用一种类型的斜杠 ('\\')。尝试使用open 测试对循环中网络驱动器上的 txt 文件的文件写入权限。
  • 我尝试了几种不同类型的斜杠组合,例如 all ('\\') 和 all ('/'),​​但没有任何改变。写访问权限似乎一直都是 True :( 我在问题中添加了更改。您还有其他建议吗?
  • 好吧,我测试了你的脚本,它可以正常工作(Win7 x64,Python 3.8 x32)。我猜您的问题与日志记录模块无关。你说你正在使用一些虚拟机。根据我的经验,VirtualBox 中的虚拟文件夹不如 real 共享文件夹可靠,因此如果您使用的是 vbox,请尝试更新它或更新 Guest Additions。
  • 感谢@viilpe 测试我的脚本并提出建议,我会看看我能做什么!
  • 脚本是否有可能意外运行两次(两个独立实例)同时或几乎同时锁定日志文件?您的问题的替代建议是在您的虚拟机上运行您的脚本,并让主机运行一个日志服务器,该服务器通过网络传递日志。另一种选择是在本地登录到 VM,然后在该过程完成后运行一个后期过程以将日志从 VM 合并/移动/覆盖到网络共享。如果您需要连接日志,也许 Pandas 可以帮助您消除欺骗。

标签: python python-3.x windows logging network-drive


【解决方案1】:

由于这并没有真正去任何地方,我将发布我为“解决”我的问题所做的事情。这不是一个令人满意的解决方案,因为当代码失败时它会失败,但总比不记录要好。 该解决方案的灵感来自这个问题的答案: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()

当代码失败但代码试图捕获大多数错误时,显然这会失败,所以我希望它会工作。我摆脱了内存处理程序,但保留了一个文件处理程序,以便在真正失败的情况下,至少记录一些日志,直到文件处理程序失败。这远非理想,但它适用于我的atm。如果您有其他建议/改进,我很乐意听到!

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-01-02
    • 2023-04-08
    • 1970-01-01
    • 1970-01-01
    • 2021-11-12
    • 2018-03-08
    相关资源
    最近更新 更多