Python のリリースごとに、新しいモジュールが追加され、新しいより良い方法が導入されます。私たちは皆、古き良き Python ライブラリや特定の方法を使用することに慣れていますが、今はアップグレードして活用する時期でもあります。新しいモジュールと改良されたモジュールとその機能についても説明します。
パスリブ
pathlib は間違いなく、Python 標準ライブラリに最近追加された最も大きなものの 1 つであり、Python 3.4 から標準ライブラリの一部となっていますが、多くの人は依然としてファイルシステム操作に os モジュールを使用しています。
ただし、pathlib には古い os.path に比べて多くの利点があります。os モジュールは生の文字列形式でパスを表現しますが、pathlib はオブジェクト指向スタイルを使用するため、より読みやすく、自然に記述できます。
from pathlib import パスインポート OS 。 パス
# 老方式
two_dirs_up = OS 。 path .dirname( os . path .dirname( os . path .abspath(__file__)))
# 新しい方法、可读性强
two_dirs_up = Path(__file__).resolve().parent.parent
パスが文字列ではなくオブジェクトとして扱われるという事実により、オブジェクトを一度作成してから、そのプロパティを検索または操作することも可能になります。
readme = Path( "README.md" ).resolve()print( f"Absolute path: {readme.absolute()} " )
# Absolute path: /home/martin/ some/path/README.md
print( f"ファイル名: {readme.name} " )
#ファイル名:README.md
print( f"パスルート: {readme.root ) } " )
# Path root: /
print( f"Parent directory: {readme.親} " )
# 親ディレクトリ: /home/martin/some/path
print( f"ファイル拡張子: {readme.suffix} " )
# ファイル拡張子: .md
print( f"Is it absolute: {readme.is_absolute()} " )
# それは絶対ですか: 本当です
pathlib の私のお気に入りの機能の 1 つは、/ (「除算」) 演算子を使用してパスを連結できることです。
# 演算子:etc = Path('/etc')
joined = etc / "cron.d" / "anacron"
print(f "存在しますか? - {joined.exists()}" )
# 存在しますか? - True
pathlib は os.path の単なる置き換えであり、os モジュール全体ではないことに注意することが重要です。pathlib には glob モジュールの機能も含まれているため、os.path を glob.glob で使用することに慣れている場合は、完全に使用できます。それらを pathlib に置き換えます。
上のスニペットでは、いくつかの便利なパス操作とオブジェクト属性を示しましたが、pathlib には、os.path で使い慣れたすべてのメソッドも含まれています。次に例を示します。
print( f"作業ディレクトリ: {Path.cwd()} " ) # os.getcwd() と同じ;作業ディレクトリ: /home/martin/some/path
Path.mkdir(Path.cwd() / "new_dir" , exist_ok = True ) # os.makedirs() と同じ
print(Path( "README.md" ).resolve()) # os.path.abspath() と同じ
# /home/martin/some/path/README.md
print(Path.home()) # os.path と同じ。
pathlib の新しい関数への os.path 関数の完全なマッピングについては、公式ドキュメントを参照してください。
秘密
os モジュールについて言えば、使用をやめるべきもう 1 つの部分は os.urandom です。代わりに、Python 3.6 以降で利用できる新しい Secret モジュールを使用する必要があります。
# 老方式:import os
length = 64
value = os.urandom(length)
print( f"Bytes: {value} " )
# Bytes: b'\xfa\xf3...\xf2\x1b\xf5\xb6'
print( f"Hex: {value.hex()} " )
# Hex: faf3cc656370e31a938e7...33d9b023c3c24f1bf5
# 新しい方法:
import secrets
value = secrets.token_bytes(length)
print( f"Bytes: {value} " )
# Bytes:
value = secrets.token_hex(length)
print( f"Hex: {value} " )
# Hex: fb5dd85e7d73f7a08b8e3...4fd9f95beb08d77391
ここで os.urandom を使用することが実際には問題ではありません。 Secrets モジュールが導入された理由は、random モジュールが暗号化セキュリティ トークンを生成しないにもかかわらず、人々がランダム モジュールを使用してパスワードなどを生成するためです。
ドキュメントによると、random モジュールはセキュリティ目的で使用すべきではなく、secrets または os.urandom を使用する必要がありますが、secrets モジュールの方が新しく、16 進トークンと URL セキュリティ トークン用のユーティリティ/便利なメソッドが含まれているため、間違いなく推奨されます。
ゾーン情報
Python 3.9 より前には、タイムゾーンを操作するための組み込みライブラリがなかったため、誰もが pytz を使用していましたが、現在は標準ライブラリにzoneinfoがあるため、切り替える時期が来ています。
日時から import datetimeimport pytz # pip install pytz
dt = datetime( 2022 , 6 , 4 )
nyc = pytz.timezone( "America/New_York" )
localized = nyc.localize(dt) )
print( f"Datetime: {localized} , Timezone: {localized.tzname()} , TZ Info: {localized.tzinfo} " )
# 新しい方法:
ゾーン情報から 輸入 ZoneInfo
nyc = ZoneInfo( "America/New_York" )
localized = datetime( 2022 , 6 , 4 , tzinfo=nyc)
print( f"Datetime: {localized}、タイムゾーン: {localized.tzname()}、 TZ 情報: {localized.tzinfo} " )
# 日時: 2022-06-04 00:00:00-04 :00、タイムゾーン: EDT、TZ 情報: アメリカ/ニューヨーク
datetime モジュールは、すべてのタイムゾーン操作を抽象基本クラス datetime.tzinfo に委任します。これには、このモジュールをインポートする前に、おそらく pytz から具体的な実装が必要です。標準ライブラリにzoneinfoがあるので、それを使用できるようになりました。
ただし、zoneinfo の使用には注意点があります。これは、タイムゾーン データがシステム上で利用可能であることを前提としています。これは UNIX システムの場合に当てはまります。システムにタイムゾーン データがない場合は、CPython によって維持される tzdata パッケージを使用する必要があります。コア開発者 IANA タイム ゾーン データベースを含むファーストパーティ ライブラリ。
データクラス
Python 3.7 への重要な追加は、namedtuple の代わりとなる dataclasses パッケージです。
なぜnamedtupleを置き換える必要があるのか不思議に思うかもしれません。データ クラスへの切り替えを検討する必要がある理由は次のとおりです。
変更可能です
repr、eq、init、hash マジック メソッドをデフォルトで提供します。
デフォルト値を指定できます。
継承がサポートされています。
さらに、データ クラスは、名前付きタプルと同等の機能を提供するために、 凍結された および スロット(3.10 以降) 属性をサポートします。
定義を変更するだけなので、切り替えはそれほど難しくありません。
# 老方式:# コレクションから 入力
から 名前付きタプルをインポート import NamedTuple
import sys
User = NamedTuple( "ユーザー" , [( "名前" , str), ( "姓" , str), ( "パスワード" , bytes)])
u = User( "John" , "Doe" , b'tfeL+uD...\xd2' )
print( f"Size: {sys.
データクラス import dataclass
@dataclass()
class ユーザー:
name: str
姓: str
パスワード: bytes
u = User( "John" , "Doe " , b'tfeL+uD...\xd2' )
print(u)
# User(name='John', surname='Doe', password=b'tfeL+uD.. .\xd2')
print( f"Size: {sys.getsizeof(u)} , {sys.
上記のコードには、サイズ比較も含めました。これは、名前付きタプルとデータクラスの大きな違いの 1 つです。上でわかるように、属性を表すためにデータクラスが dict を使用しているため、名前付きタプルのサイズははるかに小さくなります。
速度の比較に関しては、何百万ものインスタンスを作成する予定がない限り、プロパティのアクセス時間は基本的に同じか、それほど重要ではないはずです。
import timeitsetup = '''
入力から import NamedTuple
User = NamedTuple("User", [("name", str), ("surname", str), ("パスワード", bytes)])
u = User("John", "Doe", b'') ''' print( f"Access
&
nbsp ;speed: {min(timeit. repeat( 'u.name' , setup=setup, number= 10000000 ))} " )
# アクセス 速度: 0。
16838401100540068セットアップ = '''
from dataclasses import dataclass
@dataclass(slots=True)
class User:
名前: str
姓: str
パスワード: bytes
u = User("John", "Doe", b'')
'''
print( f"Access speed: {min(timeit.repeat( 'u.name' , setup=setup, number= 10000000 ))} " )
# Access speed: ;0.17728697300481144
上記の理由からデータ クラスに切り替える必要がある場合は、できるだけ早く試してみてください。
代わりに、何らかの理由で切り替えたくないが、実際にnamedtupleを使用したい場合は、少なくともコレクションのNamedTupleの代わりにtypesモジュールを使用する必要があります。
# 好ましくない方法: コレクションから import namedtuple
Point = namedtuple( "Point" , [ "x" , "y" ])
# より良い方法:
from typing NamedTuple クラス をインポートします。 ポイント(NamedTuple) : x: float y: float
最後に、名前付きタプルもデータクラスも使用していない場合は、Pydantic を直接使用することを検討してください。
適切なロギング
これは標準ライブラリに最近追加されたものではありませんが、使用する価値はあります。print ステートメントの代わりに適切なロギングを使用する必要があります。問題をローカルでデバッグする場合は print を使用できますが、ユーザーの介入なしで実行される本番対応プログラムの場合は、適切なログ記録は必須です。
特に、Python ログの設定が次のように簡単であることを考慮すると、
import logginglogging.basicConfig(
filename= 'application.log' ,
level=logging.WARNING,
format = '[% (asctime)s] {%(pathname)s:%(lineno)d} %(levelname)s - %(message)s' , datefmt =
' % H:%M:%S'
)
ログ記録。 エラー ( 「重大なエラーが発生しました。」 )
# [ 12 : 52 : } エラー - いくつかの 深刻な エラー が発生しました。
logging.warning( 'Some warning.' )
# [ 12 : 52 : 35 ] {< stdin >: 1 } WARNING - Some warning。
print ステートメントと比較して、上記のシンプルな構成は優れたデバッグ エクスペリエンスを提供します。そして最も重要なことは、ログ ライブラリをさらにカスタマイズして、別の場所にログを記録したり、ログ レベルを変更したり、ログを自動的にローテーションしたりできることです。
F 文字列
Python には、C スタイルの書式設定、f-strings、テンプレート文字列、または .format 関数など、文字列を書式設定するさまざまな方法が含まれていますが、そのうちの 1 つである f-strings は、より自然に記述された書式設定された文字列リテラルです。読みやすく、前述のオプションの中で最も高速です。
したがって、f 文字列が使用される理由について議論したり説明したりする必要はないと思いますが、f 文字列が使用できない特定の状況があります。
% 形式を使用する唯一の理由は、ログを記録するためです。
import ログ記録= 「何かが起こった...」
ロガー = logging.getLogger(__name__)
ロガー。 エラー ( "メッセージ: %s" , things) # 评估内部记录器
メソッドロガー。 エラー (f "メッセージ: {things}" ) # 立即评估
上の例では、f-strings を使用すると、式はすぐに評価されますが、C スタイルの書式設定では、置換は実際に必要になるまで延期されます。これは、すべてのメッセージが同じテンプレートを持つメッセージのグループ化にとって重要です。は 1 つとしてログに記録できますが、ロガーに渡される前にテンプレートにデータが設定されるため、これは f 文字列では機能しません。
また、実行時のテンプレートの設定など、f-string では単純に実行できないこともあります。つまり、動的書式設定です。これが、f-string がリテラル文字列形式と呼ばれる理由です。
# アニメーション設置モジュールとそのパラメータdef func (tpl: str, param1: str, param2: str) -> str: & nbsp
; return tpl.format(param=param1, param2=param2)
some_template = 「最初のテンプレート: {param1}, {param2}」
another_template = 「その他のテンプレート: {param1} and {param2}」
print(func(some_template, "Hello" , "World" ))
print(func(another_template,
inputs = [ "Hello" , 「世界」 、 「!」 ]
テンプレート = value の「ここにいくつかの動的 value: {value}」があり ます
。 入力内 :
print(template.format(value=value))
最も重要なことは、f-string の方が読みやすく、パフォーマンスが高いため、可能な限り f-string を使用することです。ただし、他の書式設定スタイルが優先されたり必要とされる状況も依然として存在することに注意してください。
トリブ
TOML は広く使用されている構成形式であり、pyproject.toml 構成ファイルで使用されるため、Python のツールとエコシステムにとって特に重要です。これまでは、TOML ファイルを管理するには外部ライブラリを使用する必要がありましたが、Python 3.11 以降では、外部ライブラリを使用する必要がありました。これは、toml パッケージに基づいた、tomllib という組み込みライブラリです。
したがって、Python 3.11 に切り替えたら、import tomli の代わりに import tomllib を使用する習慣を身に付ける必要があります。心配する依存関係が 1 つ減ります。
# トムリ をインポートします as tomllibimport tomllib
with open( "pyproject.toml" , "rb" ) f: &
nbsp; config = tomllib.load(f)
print (config)
# { 'プロジェクト' : { '作成者' : [{ 'メール' : '[email protected]' ,
# &注意; 「名前」 : 'マルティン ハインツ' }],
# '依存関係' : [ 'フラスコ' , 「リクエスト」 ]、
# 「説明」 : 'パッケージの例' ,
# 「名前」 : 'some-app' 、
# 「バージョン」 : 「0.1。 0' }}
toml_string = """
[プロジェクト]
名 = 「別のアプリ」
説明 = 「サンプル パッケージ」
バージョン = "0.1.1"
"""
config = tomllib.loads(toml_string)
print (config)
# { 'プロジェクト' : { '名前' : 「別のアプリ」 、 「説明」 : 「パッケージの例」 、 「バージョン」 : '0.1.1' }}
セットアップツール
最後のものは非推奨の通知に似ています。
Distutils は非推奨であるため、distutils の関数やオブジェクトの使用も同様に推奨されず、Setuptools はそのような使用をすべて置き換えるか非推奨にすることを目的としています。
distutils パッケージに別れを告げ、setuptools に切り替える時が来ました。setuptools のドキュメントには、distutils の使用法を置き換える方法に関するガイダンスが記載されています。さらに、PEP 632 では、setuptools でカバーされていない distutils の部分についての移行アドバイスが提供されています。
要約する
Python の新しいバージョンには新しい機能が含まれているため、Python リリース ノートの「新しいモジュール」、「非推奨のモジュール」、「削除されたモジュール」のセクションを確認することをお勧めします。これは、Python 標準を理解する上で重要です。これにより、新しい機能やベスト プラクティスを常にプロジェクトに組み込むことができます。