1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

python3.4で導入されたPathlibのsuffix間違ってね?って話

Posted at

Pathlibのsuffix間違ってね?

端的に言えばディレクトリに対してsuffixを呼び出した場合、必ず空文字が帰ってくるわけではない。

ディレクトリ名に「.」が含まれている場合、そこから後ろの文字列が返却される。

自分のsuffixに対する理解

公式ドキュメントの一部抜粋

末尾の要素に拡張子があればそれになります:
>>> PurePosixPath('my/library/setup.py').suffix
'.py'
>>> PurePosixPath('my/library.tar.gz').suffix
'.gz'
>>> PurePosixPath('my/library').suffix
''

このサンプルの三番目で、ディレクトリに対してsuffixを呼び出したら、空文字が帰ってきている。
なのでsuffixはファイルの場合は拡張子、ディレクトリの場合は空文字が帰ってくると思った。

たとえ↓のようなディレクトリ名であっても空文字が返却されると思った。

>>> PurePosixPath('my/library.d').suffix
''

実際のsuffixの処理

実際に実行してみる

>>> PurePosixPath('my/library.d').suffix
'.d'

まさかの'.d'。
空文字ではなく'.d'。

実際のpathlib.pyのsuffixのコードを見てみる

pathlib.py
~省略~
@property
def suffix(self):
    """The final component's last suffix, if any."""
    name = self.name
    i = name.rfind('.')
    if 0 < i < len(name) - 1:
        return name[i:]
    else:
        return ''
~省略~

見ての通り、単純に'.'を探してあったら切り取ってるだけだった。
ディレクトリかどうかをチェックしていないので、ディレクトリだったとしてもファイルと同様の処理をしている。
そのため、ディレクトリであってもsuffixが空文字以外が返却される可能性がある。

気づいた理由

from pathlib import Path


def print_ext(path: Path):
    ext = path.suffix
    if ext == '':
        print('dir')
    elif ext == '.py':
        print('py file')
    else:
        print('other file')


if __name__ == '__main__':
    print_ext(Path('my/library.d'))
    print_ext(Path('my/library.d/setup.py'))
    print_ext(Path('my/library.d/image.jpg'))

実行結果として下のようになると思った。

dir
py file
other file

でも実際は、

other file
py file
other file

解決策

suffixはディレクトリかどうかを確認していないのがそもそもの原因なのでこちらでそれをやってあげる。

from pathlib import Path


def print_ext(path: Path):
    ext = path.suffix
    if path.is_dir():
        print('dir')
    elif ext == '.py':
        print('py file')
    else:
        print('other file')


if __name__ == '__main__':
    print_ext(Path('my/library.d'))
    print_ext(Path('my/library.d/setup.py'))
    print_ext(Path('my/library.d/image.jpg'))

このようにis_dir()でディレクトリかどうかをチェックしてそれを条件にすることで解決する。

まとめ

そもそもis_dir()でディレクトリかファイルかのチェックを怠ったのが原因だった。
しかし、ドキュメントも悪い気がする。
ディレクトリに対してsuffixを呼んだ場合のことは文章としては書いていないが、
サンプルの書き方的には、誤解する人がでてきてしまうと思う。
これって仕様なのかな?

pathlib.py
~省略~
@property
def suffix(self):
    if self.is_dir():
        return ''
    """The final component's last suffix, if any."""
    name = self.name
    i = name.rfind('.')
    if 0 < i < len(name) - 1:
        return name[i:]
    else:
        return ''
~省略~

ってやってくれればありがたいんだけどね。

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?