Skip to content

Docs: the difference between Path.rename() and Path.replace() is not obvious #72073

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

Closed
asvetlov opened this issue Aug 28, 2016 · 6 comments
Closed
Labels
3.9 only security fixes 3.10 only security fixes docs Documentation in the Doc dir easy type-bug An unexpected behavior, bug, or error

Comments

@asvetlov
Copy link
Contributor

BPO 27886
Nosy @pitrou, @ezio-melotti, @bitdancer, @asvetlov, @eryksun

Note: these values reflect the state of the issue at the time it was migrated and might not reflect the current state.

Show more details

GitHub fields:

assignee = None
closed_at = None
created_at = <Date 2016-08-28.19:07:12.342>
labels = ['easy', 'type-bug', '3.8', '3.9', '3.10', 'library', 'docs']
title = 'Docs: the difference between Path.rename() and Path.replace() is not obvious'
updated_at = <Date 2021-03-13.00:14:05.849>
user = 'https://github.com/asvetlov'

bugs.python.org fields:

activity = <Date 2021-03-13.00:14:05.849>
actor = 'eryksun'
assignee = 'docs@python'
closed = False
closed_date = None
closer = None
components = ['Documentation', 'Library (Lib)']
creation = <Date 2016-08-28.19:07:12.342>
creator = 'asvetlov'
dependencies = []
files = []
hgrepos = []
issue_num = 27886
keywords = ['easy']
message_count = 5.0
messages = ['273836', '273839', '273840', '273841', '388570']
nosy_count = 6.0
nosy_names = ['pitrou', 'ezio.melotti', 'r.david.murray', 'asvetlov', 'docs@python', 'eryksun']
pr_nums = []
priority = 'low'
resolution = None
stage = None
status = 'open'
superseder = None
type = 'behavior'
url = 'https://bugs.python.org/issue27886'
versions = ['Python 3.8', 'Python 3.9', 'Python 3.10']

@asvetlov
Copy link
Contributor Author

Hi.

On reading the doc for pathlib I've stuck with .rename() and .replace() (https://docs.python.org/3/library/pathlib.html#pathlib.Path.rename).

What's the difference?

Going to pathlib's source code I've figured out that methods are use different functions from os module: os.rename() and os.replace().

But the documentation for os module is not obvious too:
the docs for both functions are almost equal from my perspective, the only significant difference is that os.rename() suggests to use os.replace() for cross-compatibility.

Could anybody explain the difference?

Also, at least the doc for pathlib.Path.rename worth to have a sentence like borrowed from os.rename: "If you want cross-platform overwriting of the destination, use replace()."

@asvetlov asvetlov added docs Documentation in the Doc dir easy type-bug An unexpected behavior, bug, or error labels Aug 28, 2016
@bitdancer
Copy link
Member

The existing docs are pretty clear on the difference: rename is only guaranteed to replace an existing file on unix (which I think means posix in this context), whereas replace always replaces the file, regardless of platform.

I'm actually surprised that rename is even part of the pathlib API, since its cross platform behavior is not consistent. It also seems as though the replace docs are incorrect, since they imply directories are replaced, but the os docs say they are not.

The "this is a posix requirement" note in os.replace also seems imprecise. Windows is not posix, so that note leaves me wondering if replace is atomic on Windows or not. That should be clarified one way or another.

I think adding the cross platform note in the pathlib docs is reasonable, since it addresses the question of why there are two similar functions.

@asvetlov
Copy link
Contributor Author

Just keeping the reference to os.rename(): https://docs.python.org/3/library/os.html#os.rename

Aha, os.rename says: "On Unix, if dst exists and is a file, it will be replaced silently if the user has permission." and "On Windows, if dst already exists, OSError will be raised even if it is a file."

Sorry, I've missed this.

Maybe it worth to add `.. warning:` section for both `os.rename` and `pathlib.Path.rename`?

@bitdancer
Copy link
Member

No, we don't like to overuse warnings.

@eryksun
Copy link
Contributor

eryksun commented Mar 13, 2021

The pathlib documentation of Path.rename() says "[o]n Unix, if target exists and is a file, it will be replaced silently if the user has permission". This leaves the behavior on Windows in question. The reader has to scroll down to the correspondence table to link to the documentation of os.rename() and presume that Path.rename() also raises FileExistsError for this case. The Path.rename() docs should just state upfront that "[o]n Windows, if target exists, FileExistsError will be raised".

@eryksun eryksun added 3.8 (EOL) end of life 3.9 only security fixes 3.10 only security fixes stdlib Python modules in the Lib dir labels Mar 13, 2021
@eryksun eryksun changed the title Docs: the difference between rename and replace is not obvious Docs: the difference between Path.rename() and Path.replace() is not obvious Mar 13, 2021
@ezio-melotti ezio-melotti transferred this issue from another repository Apr 10, 2022
@codecivet
Copy link

I just wanted to note that I find the current documentation confusing. I had to search and find this issue report to understand the difference. As mentioned above the effect of Path.rename on non-Unix systems is ambiguous in the current documentation, so it is not clear how replace differs from rename.

@AlexWaygood AlexWaygood removed 3.8 (EOL) end of life stdlib Python modules in the Lib dir labels Apr 25, 2022
miss-islington added a commit that referenced this issue May 20, 2022
miss-islington added a commit that referenced this issue May 20, 2022
@slateny slateny closed this as completed May 21, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
3.9 only security fixes 3.10 only security fixes docs Documentation in the Doc dir easy type-bug An unexpected behavior, bug, or error
Projects
None yet
Development

No branches or pull requests

6 participants