Fundamentals 13 min read

Modern Python Standard Library: Pathlib, Secrets, ZoneInfo, Dataclasses, Logging, f‑strings, Tomllib, and Setuptools

This article reviews several modern Python standard‑library modules—Pathlib, Secrets, ZoneInfo, Dataclasses, proper logging, f‑strings, Tomllib, and Setuptools—explaining why they replace older alternatives and providing concise code examples to help developers adopt best practices and keep their projects up‑to‑date.

Python Programming Learning Circle
Python Programming Learning Circle
Python Programming Learning Circle
Modern Python Standard Library: Pathlib, Secrets, ZoneInfo, Dataclasses, Logging, f‑strings, Tomllib, and Setuptools

Python continuously adds new standard‑library modules; this article highlights several modern replacements for older approaches and demonstrates their usage with concise code examples.

Pathlib instead of os

Pathlib, introduced in Python 3.4, offers an object‑oriented API for filesystem paths, improving readability and allowing operations like Path(__file__).resolve().parent.parent and using the division operator to join paths.

<code>from pathlib import Path
import os.path

# old way
two_dirs_up = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
# new way
two_dirs_up = Path(__file__).resolve().parent.parent
</code>

Path objects expose useful properties such as .absolute() , .name , .root , .parent , .suffix , and .is_absolute() .

<code>readme = Path("README.md").resolve()
print(f"Absolute path: {readme.absolute()}")
print(f"File name: {readme.name}")
print(f"Path root: {readme.root}")
print(f"Parent directory: {readme.parent}")
print(f"File extension: {readme.suffix}")
print(f"Is it absolute: {readme.is_absolute()}")
</code>

Pathlib also supports the / operator for path concatenation.

<code>etc = Path('/etc')
joined = etc / "cron.d" / "anacron"
print(f"Exists? - {joined.exists()}")
</code>

Secrets instead of os.urandom

The secrets module (available since Python 3.6) should replace os.urandom for generating cryptographically strong tokens.

<code># old way
import os
value = os.urandom(64)
print(f"Bytes: {value}")
print(f"Hex: {value.hex()}")

# new way
import secrets
value = secrets.token_bytes(64)
print(f"Bytes: {value}")
value = secrets.token_hex(64)
print(f"Hex: {value}")
</code>

ZoneInfo instead of pytz

Python 3.9 introduced zoneinfo as the standard way to handle time zones, replacing the external pytz library.

<code># old way
import pytz
from datetime import datetime
nyc = pytz.timezone("America/New_York")
localized = nyc.localize(datetime(2022, 6, 4))
print(f"Datetime: {localized}, Timezone: {localized.tzname()}, TZ Info: {localized.tzinfo}")

# new way
from zoneinfo import ZoneInfo
from datetime import datetime
nyc = ZoneInfo("America/New_York")
localized = datetime(2022, 6, 4, tzinfo=nyc)
print(f"Datetime: {localized}, Timezone: {localized.tzname()}, TZ Info: {localized.tzinfo}")
</code>

If the system lacks zone data, install the tzdata package.

Dataclasses instead of NamedTuple

Python 3.7 added dataclasses as a flexible alternative to NamedTuple , offering mutability, default values, and automatic method generation.

<code># old way (namedtuple)
from typing import NamedTuple
class User(NamedTuple):
    name: str
    surname: str
    password: bytes

# new way (dataclass)
from dataclasses import dataclass

@dataclass()
class User:
    name: str
    surname: str
    password: bytes
</code>

Dataclasses are larger in memory because they store attributes in a dict, but attribute access speed is comparable.

Proper Logging instead of print

For production code, use the logging module rather than print statements.

<code>import logging
logging.basicConfig(
    filename='application.log',
    level=logging.WARNING,
    format='[%(asctime)s] {%(pathname)s:%(lineno)d} %(levelname)s - %(message)s',
    datefmt='%H:%M:%S'
)
logging.error("Some serious error occurred.")
logging.warning('Some warning.')
</code>

f‑strings instead of format

f‑strings provide readable, high‑performance string interpolation, though % formatting may still be useful for deferred logging.

<code># logging with % formatting (deferred)
logger.error("Message: %s", things)
# immediate evaluation with f‑string
logger.error(f"Message: {things}")
</code>

Tomllib instead of tomli

Python 3.11 includes the built‑in tomllib module for parsing TOML, removing the need for the external tomli package.

<code>import tomllib
with open("pyproject.toml", "rb") as f:
    config = tomllib.load(f)
    print(config)

toml_string = """
[project]
name = "another-app"
description = "Example Package"
version = "0.1.1"
"""
config = tomllib.loads(toml_string)
print(config)
</code>

Setuptools instead of distutils

Since distutils is deprecated, migrate to setuptools for packaging; see PEP 632 for migration guidance.

Conclusion

Each new Python release adds useful modules and deprecates old ones. Regularly reviewing the release notes for “new modules”, “deprecated modules”, and “removed modules” helps you keep your projects modern and maintainable.

Loggingstandard-librarypathlibdataclasses
Python Programming Learning Circle
Written by

Python Programming Learning Circle

A global community of Chinese Python developers offering technical articles, columns, original video tutorials, and problem sets. Topics include web full‑stack development, web scraping, data analysis, natural language processing, image processing, machine learning, automated testing, DevOps automation, and big data.

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.