-
-
Notifications
You must be signed in to change notification settings - Fork 32.4k
bpo-44186: prevent TimedRotatingFileHandler overwriting log files #26553
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
823c5ff
f2f269a
b6d220f
8b21aa5
15ce117
d120312
1f94389
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -255,6 +255,7 @@ def __init__(self, filename, when='h', interval=1, backupCount=0, | |
raise ValueError("Invalid rollover interval specified: %s" % self.when) | ||
|
||
self.extMatch = re.compile(self.extMatch, re.ASCII) | ||
self.file_number = re.compile(r'\(([0-9]+)\)$') | ||
self.interval = self.interval * interval # multiply by units requested | ||
# The following line added because the filename passed in could be a | ||
# path object (see Issue #27493), but self.baseFilename will be a string | ||
|
@@ -401,8 +402,12 @@ def doRollover(self): | |
timeTuple = time.localtime(t + addend) | ||
dfn = self.rotation_filename(self.baseFilename + "." + | ||
time.strftime(self.suffix, timeTuple)) | ||
if os.path.exists(dfn): | ||
os.remove(dfn) | ||
while os.path.exists(dfn): | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think this would be more future-proof if it were structured as: if os.path.exists(dfn):
self.backup_existing(dfn) and the new def backup_existing(self, dfn):
"""
Back up an existing file with the same name `dfn` as a destination file for rollover.
This method must find a unique filename in the same directory, related to `dfn`,
and rename the existing file to that name.
This implementation appends ' (N)' to `dfn`, where N is an integer going up from 1
until an integer value N is found such that no existing file with that ' (N)' suffix is found.
""" Having a separate method allows someone with a custom scheme for naming logfiles (using the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Sorry for being slow, I just wanted to clear make sure I have the correct understanding. I agree that the having a separate I wasn't 100% sure on the behaviour of the method though, from my understanding on the rollover, the new file should be created with a suffix, from the docstring above, it seems like you want to rename the existing file to have a suffix? as an example, I have the following log files
for all the examples below, I'll denote that structure as
I was imagining the behaviour below:
This would mean that for n files, the latest file would always have the highest suffix. The current log would obviously have no suffix, the oldest rollover log would only have the date, and the following files would have (1), ... (N) in the order that they were generated. From reading your comment, implemeting that method would yield the behaviour below:
where the most recent file would rename the already existing file in the directory and "bump" it up a number. Personally I prefer the first method as implementing the method this way could cause some ambiguity i.e. in the case of a directory with suffixes I'm not sure how this different logic affects the other issues you linked, I had a look at them but I need to do some testing to see the results myself as I couldn't 100% follow just the PR and bpo. I'll try and implement the logic and update this PR tonight. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Don't rush to update the PR, because maybe we should think about things some more. I'm not able to say much at the minute as I'm pressed for time, but I was thinking along the lines of: a target file that exists when rolling over should be an unusual case, not a common case (This issue hasn't come up in the many years since There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Yes, good point. The original logging module was written back before PEP8, and kept the old-style naming for backward compatibility. So |
||
if match := re.search(self.file_number, dfn): | ||
name = re.sub(self.file_number, f'({int(match.groups()[0]) + 1})', dfn) | ||
dfn = self.rotation_filename(name) | ||
else: | ||
dfn = self.rotation_filename(self.baseFilename + '.' + time.strftime(self.suffix, timeTuple) + ' (2)') | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I was attempting to mimic the default behaviour I saw from Windows 10, in Windows if you create a new document with a duplicate name it will create the documents like this:
On my Mac it omits the parenthesis and creating new documents yields a naming scheme like
I personally preferred the bracketed naming scheme but that is really just my personal preference. I don't know of anywhere else this pops up in the standard library but if there's a convention that I'm not following I'd be happy to rework that. |
||
self.rotate(self.baseFilename, dfn) | ||
if self.backupCount > 0: | ||
for s in self.getFilesToDelete(): | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I was looking at other issues recently - bpo-43344, bpo-44753 - so this solution might not work in those scenarios. Specifcally, in scenarios where the user wants to keep the suffix as ".log" or similar. After changes to address those issues, rollover logic expects rolled-over files to start with the base filename (minus extension) + ".", and contain
self.extMatch
. I've also added comments on the issue itself.