python / python/cpython

pathlib: Path('.').exists() returns True when current working directory (cwd) was deleted

オープン
#127,264 コメント 8 件 リアクション 0 件 担当者 0 名 GitHub で見る

まだ誰も着手していません。

stdlib topic-pathlib type-bug
主要言語
Python
スター
77.2k
フォーク
36k
PR マージ指標
PR 指標を取得中

説明

Bug report

Bug description:

Path.exists() and Path.resolve() do not work consistently with each other if the current working directory is deleted after Python is launched.

For example, if I open a Python 3.13.0 interpreter (although I have verified this occurs in older versions as well) in a directory, and then delete that directory I experience the following behavior:

>>> from pathlib import Path
>>> Path('.').exists()
True
>>> Path('.').resolve()
Traceback (most recent call last):
  File "<python-input-2>", line 1, in <module>
    Path('.').resolve()
    ~~~~~~~~~~~~~~~~~^^
  File "/opt/homebrew/Caskroom/mambaforge/base/envs/py313minimal/lib/python3.13/pathlib/_local.py", line 670, in resolve
    return self.with_segments(os.path.realpath(self, strict=strict))
                              ~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^
  File "<frozen posixpath>", line 413, in realpath
FileNotFoundError: [Errno 2] No such file or directory

Note how Path('.').exists() is True, even though the cwd does not exist, and then when I try to resolve the path, I get a FileNotFoundError.

You also get a FileNotFoundError when the cwd doesn't exist for all relative paths, even though in the non-dot cases Path.exists() works as one would expect.

>>> Path('asdf').exists()
False
>>> Path('asdf').resolve().exists()
Traceback (most recent call last):
  File "<python-input-4>", line 1, in <module>
    Path('asdf').resolve().exists()
    ~~~~~~~~~~~~~~~~~~~~^^
  File "/opt/homebrew/Caskroom/mambaforge/base/envs/py313minimal/lib/python3.13/pathlib/_local.py", line 670, in resolve
    return self.with_segments(os.path.realpath(self, strict=strict))
                              ~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^
  File "<frozen posixpath>", line 413, in realpath
FileNotFoundError: [Errno 2] No such file or directory

If the cwd does exist, you can see that Path.resolve() does not raise a FileNotFoundError when the path does not exist.

>>> from pathlib import Path
>>> Path('asdf').exists()
False
>>> Path('asdf').resolve()
PosixPath('/Users/danielblanchard/asdf')

I believe resolve is doing the right thing here, but two things are not working as expected when the cwd is deleted:

  1. Path('.').exists() and Path('').exists() should not tell you a path exists that doesn't.
  2. Path('foo').resolve() should not raise a FileNotFoundError if the cwd doesn't exist, unless strict=True. Instead it should just return the initial path.
CPython versions tested on:

3.9, 3.12, 3.13

Operating systems tested on:

Linux, macOS

Linked PRs
  • gh-135531

コントリビューションガイド

コントリビューションガイドを開く

はじめの一歩

  1. issue を最後まで読み、次にプロジェクトのコントリビューションガイドを読みます。
  2. 着手することを issue にコメントします — 二人が同じ作業をするのを防げます。
  3. リポジトリをフォークし、ブランチを切って変更します。
  4. issue 番号を参照したプルリクエストを送ります。

調査の方向性

pathlib/_local.py の Path.exists() と Path.resolve() から始め、現在の作業ディレクトリが削除された場合の相対パスに対する os.path.realpath の使用箇所を追跡します。'.'、''、'foo' に対して報告される動作を比較します。exists() が削除された現在の作業ディレクトリを報告しなくなり、resolve() が strict=True の場合にのみ FileNotFoundError を送出するようになれば完了です。gh-135531 は関連する作業がすでに進行中であることを示しています。

索引モデルが issue の本文から書いたものです。

評価

技術スタック
python
領域
operating-systems
issue の種類
バグ
難易度
3/5
見積もり時間
1〜2日
活発さ
停滞
明瞭さ
おおむね明確
初心者へのやさしさ
25/100

新しい issue をメールで受け取る

初心者向けの GitHub issue を短くまとめたダイジェスト。