なぜpathlibを使うことに慣れなければならないのですか?

7944 ワード

数年前、Pythonの新しいpathlibモジュールを見つけたとき、os.pathモジュールの少し不器用で不要なオブジェクト向けバージョンだと思っていました.私は間違っています.Pythonのpathlibモジュールは実際には素晴らしい!
本稿では、pathlibであなたにセールスを試みます.Pythonのファイルを使用する必要があるときにPythonのpathlibモジュールを使用することを奨励したいと思います.
os.path不器用
os.pathモジュールは、Pythonのパスを処理するためのライブラリです.必要なものはほとんど含まれていませんが、時には重く見えます.
このように導入すべきですか?
import os.path

BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
TEMPLATES_DIR = os.path.join(BASE_DIR, 'templates')

それともこんな感じ?
from os.path import abspath, dirname, join

BASE_DIR = dirname(dirname(abspath(__file__)))
TEMPLATES_DIR = join(BASE_DIR, 'templates')

あるいは、このjoin関数の名前はあまりにも漠然としていて、私たちはこのようにすることができます.
from os.path import abspath, dirname, join as joinpath

BASE_DIR = dirname(dirname(abspath(__file__)))
TEMPLATES_DIR = joinpath(BASE_DIR, 'templates')

しかし、これらは少し気まずいと思います.文字列を返す関数に渡し、文字列を返す他の関数に渡します.これらの文字列はパスを表すことができますが、文字列にすぎません.
複数の関数がネストするとos.pathでは文字列が文字列に入ってクラスを出す関数が不器用で、コードを内向的に読む必要があります.これらのネストされた関数呼び出しをチェーンメソッド呼び出しに変換できれば、これは良いのではないでしょうか.pathlibモジュールがあれば、私たちはできます!
from pathlib import Path

BASE_DIR = Path(__file__).resolve().parent.parent
TEMPLATES_DIR = BASE_DIR.joinpath('templates')

os.pathモジュールには関数のネストが必要ですが、pathlibモジュールのpathクラスでは、Pathオブジェクト上のメソッドとプロパティをチェーン操作して、等価なパス表現を得ることができます.
待って、これらのパスオブジェクトは同じことではありません:それらはオブジェクトで、パス文字列ではありません!急いでいません.後でこの問題について説明します(ヒント:これらの文字列はほとんどパス文字列と交換して使用できます).
osモジュールの肥大化
Pythonクラシックモジュールos.pathは、パスを処理するためにのみ使用される.本当にパスで何かをしたい(ディレクトリを作成するなど)と思ったら、別のPythonモジュールを使う必要があります.通常はosの下のモジュールでもあります.
osモジュールには、mkdir、getcwd、chmod、stat、remove、rename、rmdirなど、ファイルとディレクトリを処理するためのツールがたくさんあります.chdir、link、wald、listdir、makedirs、rename、remvedirs、unlink(removeと同じ)、symlinkもあります.また、fork、getenv、putenv、environ、getlogin、systemなど、ファイルシステムとはまったく関係のないものがたくさんあります.ここに羅列されていないものもたくさんあります.
Pythonのosモジュールは何でもできる.システム関連のおでんに似ていますOSモジュールには良いものがたくさんありますが、OSモジュールでパスやファイルシステムに関連するコンテンツを検索したい場合は、さらに掘り起こす必要があります.
pathlibモジュールは、ファイルシステムに関連するos機能の多くをpathオブジェクト上の方法で置き換えた.
次のコードは、src/_pypackages_ディレクトリを作成し、.editorconfigファイルの名前をsrc/.editorconfigに変更します.
import os
import os.path

os.makedirs(os.path.join('src', '__pypackages__'), exist_ok=True)
os.rename('.editorconfig', os.path.join('src', '.editorconfig'))

Pathオブジェクトを使用して同じ操作を行います.
from pathlib import Path

Path('src/__pypackages__').mkdir(parents=True, exist_ok=True)
Path('.editorconfig').rename('src/.editorconfig')

チェーンメソッドのためpathlibコードはパスを1位にします!
Pythonの禅が言ったように、「名前空間は素晴らしい考えで、私たちにもっと多くのことをさせます」.osモジュールは非常に大きな名前空間で、中にはたくさんのものが入っています.pathlib.pathクラスはosモジュールよりも小さく、ターゲットが明確なネーミングスペースです.このパスネーミングスペースのメソッドは、文字列接合のネストされた関数呼び出しではなく、メソッドチェーン操作を可能にするパスオブジェクトを返します.
GLOBモジュールもあることを忘れないでください!
osとos.PathモジュールはPython標準ライブラリで唯一ファイルパス/ファイルシステムに関連する機能モジュールではありません.globモジュールは、別の処理パスに関連するモジュールです.glob.glob関数を使用して、特定のモードに一致するファイルを検索できます.
from glob import glob

top_level_csv_files = glob('*.csv')
all_csv_files = glob('**/*.csv', recursive=True)

新しいpathlibモジュールにはglobのような機能も含まれています.
from pathlib import Path

top_level_csv_files = Path.cwd().glob('*.csv')
all_csv_files = Path.cwd().rglob('*.csv')

pathlibを重度に使用すると、globモジュールの存在を完全に忘れる可能性があります.PATHオブジェクトがすでに提供しているすべてのglobモジュールが備えている機能です.
pathlibは簡単を簡単にします
pathlibモジュールは多くの複雑な状況を簡単にしますが、簡単なことをもっと簡単にすることもできます.
1つ以上のファイルのすべてのテキストを読み込む必要がありますか?
with文ブロックを使用してファイルを開き、その内容を読み取り、ファイルを閉じることができます.
from glob import glob

file_contents = []
for filename in glob('**/*.py', recursive=True):
    with open(filename) as python_file:
        file_contents.append(python_file.read())

あるいは、Pathオブジェクトのread_を使うことができます.textメソッドでは、1行のコードでリスト解析機能でファイルの内容を新しいリストに読み込みます.
from pathlib import Path

file_contents = [
    path.read_text()
    for path in Path.cwd().rglob('*.py')
]

もし私がファイルに書き込む必要があるなら?
Openコンテキストマネージャを使用すると、次のことができます.
with open('.editorconfig') as config:
    config.write('# config goes here')

またはwrite_を使用しますtextメソッド:
Path('.editorconfig').write_text('# config goes here')

Open(コンテキストマネージャとしても他の方法としても)を使用するのが好きな場合は、PATHオブジェクト上でOPENメソッドを使用することもできます.
from pathlib import Path

path = Path('.editorconfig')
with path.open(mode='wt') as config:
    config.write('# config goes here')

または、Python 3.6から、PATHオブジェクトを内蔵open関数に渡すこともできます.
from pathlib import Path

path = Path('.editorconfig')
with open(path, mode='wt') as config:
    config.write('# config goes here')

PATHオブジェクトはあなたのコードをより明確にします
次の3つの変数は何を指しますか?値は何を表しますか?
person = '{"name": "Trey Hunner", "location": "San Diego"}'
pycon_2019 = "2019-05-01"
home_directory = '/home/trey'

これらの変数のそれぞれは文字列を指します.
これらの文字列は異なるものを表しています.一つはJSON blobで、一つは日付で、もう一つはファイルパスです.
以下に、これらのオブジェクトのより有用な表現を示します.
from datetime import date
from pathlib import Path

person = {"name": "Trey Hunner", "location": "San Diego"}
pycon_2019 = date(2019, 5, 1)
home_directory = Path('/home/trey')

JSONオブジェクトは辞書に逆シーケンス化でき、日付はローカルでdatetimeを使用する.dateオブジェクトは、ファイルシステムパスがpathlibを使用できるようになったことを示す.pathオブジェクトは統一的に表示されます.
Pathオブジェクトを使用すると、コードをより明確にすることができます.日付を表す場合は、Dateオブジェクトを使用します.ファイルパスを表示しようとすると、Pathオブジェクトを使用できます.
私はオブジェクト向けプログラミングの確固たる擁護者ではありません.クラスは別の抽象層を追加しますが、抽象はより複雑で単純化を維持できない場合があります.でもpathlib.Pathクラスは有用な抽象です.それは急速に普遍的に受け入れられる抽象になっている.
PEP 519に感謝します.ファイルパスオブジェクトは現在、パスを使用する基準となっています.Python 3.6にはopen関数とos、shutil、osが内蔵.pathモジュールの各種関数はpathlib.pathオブジェクトは一緒に正常に動作します.ほとんどの使用パスのコードを変更する必要がなく、pathlibを今から使用することができます.
pathlibには何が欠けていますか?
pathlibは偉大だが、万象を網羅しているわけではない.私は何気なくいくつかの欠落した特性を発見しました.pathlibモジュールがこれらの特性を含むことを望んでいます.
私が気づいた最初の欠陥はpathlibです.Pathのメソッドにはshutilと同等の機能が欠けている.
パスオブジェクト(および類似パスのオブジェクト)を上位レベルのshutil関数に渡してファイルやディレクトリをコピー/削除/移動することはできますが、Pathオブジェクトにはこれと同等の方法はありません.
したがって、ファイルをコピーするには、次の操作を行う必要があります.
from pathlib import Path
from shutil import copyfile

source = Path('old_file.txt')
destination = Path('new_file.txt')
copyfile(source, destination)

同じくosとはchdir等価pathlib機能.
これは、現在の作業ディレクトリを変更する必要がある場合、chdirをインポートする必要があることを意味します.
from pathlib import Path
from os import chdir

parent = Path('..')
chdir(parent)

osともwalk関数等価pathlib関数.pathlibを使用して独自のwalk式関数を簡単に作成できますが.
私はpathlib.Pathオブジェクトは、最終的には、いくつかの欠落した動作の方法を含んでもよい.これらの欠落した特性にもかかわらず、os.path系を使用するよりも「pathlib系」を使用するほうが管理しやすいと思います.
pathlibを常に使うべきですか?
Python 3から6から、pathlib.Pathオブジェクトは、パス文字列が使用されているほとんどの場所で動作します.だから、Python 3を使っているなら.6(またはそれ以上のバージョン)では、pathlibを使用しない理由はないと思います.
python 3の以前のバージョンを使用している場合は、pathオブジェクトをstr呼び出しに常にパッケージして、文字列をエスケープする必要がある場所で対応する文字列の戻りを取得できます.ちょっと気まずいですが、役に立ちます.
from os import chdir
from pathlib import Path

chdir(Path('/home/trey'))  # Python 3.6+  
chdir(str(Path('/home/trey')))  #     Python 3  

どのバージョンのPython 3を使用しているかにかかわらず、pathlibを試してみることをお勧めします.
何?まだPython 2を使ってるの?よし、万能のPyPIにサードパーティ製ツールpathlib 2モジュールがあるのは選択肢ですが、今ではどんなバージョンのPythonでもpathlibを使用することができます!
pathlibで私のコードをもっと読みやすくします.今、私がファイルを処理するほとんどのコードはpathlibをデフォルトで使用しています.あなたもそうすることをお勧めします.pathlibが使えるなら、できるだけ使いましょう.
原文:https://treyhunner.com/2018/12/why-you-should-be-using-pathlib/