Session lifecycle, working directories, and logging configuration for Python applications
Project description
Session Management
Purpose
VCollab applications need a consistent way to manage execution
sessions — creating work directories, configuring logging, and
cleaning up after completion. The vcti-session package provides
session lifecycle management with automatic directory creation,
configurable cleanup policies, and integrated logging setup.
Dependencies: pydantic, python-dotenv, vcti-logging, vcti-config
Installation
# Latest main branch
pip install vcti-session
### In `requirements.txt`
vcti-session>=1.0.1
### In `pyproject.toml` dependencies
```toml
dependencies = [
"vcti-session>=1.0.1",
]
Quick Start
Auto-managed session directory
from pathlib import Path
from vcti.session import SessionDir, SessionHandler, LogConfig
session_dir = SessionDir(
base_directory=Path("/tmp/sessions"),
max_session_dirs=10,
max_age_days=7,
)
log_config = LogConfig(file_path="logs/app.log", console_enabled=True)
handler = SessionHandler(session_dir, log_config)
with handler.session_context() as session:
print(f"Working in: {session.path}")
# Session directory auto-created with unique name
# Logging configured to session_path/logs/app.log
# Old sessions pruned automatically on exit
User-specified work directory
from vcti.session import WorkDir, LogConfig
work_dir = WorkDir(
directory="/path/to/my/work",
log_config=LogConfig(file_path="app.log"),
create_if_missing=True,
)
with work_dir.work_context():
print(f"Working in: {work_dir.path}")
Configuration from environment variables
# SessionDir reads: SESSION_DIR_PREFIX, SESSION_DIR_MAX_SESSION_DIRS, etc.
session_dir = SessionDir(
base_directory="/tmp/sessions",
env_prefix="MYAPP_", # reads MYAPP_SESSION_DIR_PREFIX, etc.
env_file=".env", # load from .env file
)
# LogConfig reads: SESSION_LOG_FILE_PATH, SESSION_LOG_LEVEL, etc.
log_config = LogConfig(
env_prefix="MYAPP_",
default_file_path="logs/app.log",
default_level="info",
)
Lifecycle hooks
SessionHandler supports optional callbacks at key lifecycle points:
def archive_sessions(dirs: list[Path]):
for d in dirs:
upload_to_s3(d)
def notify_created(path: Path):
print(f"Session started: {path}")
def on_exit(path: Path, error: Exception | None):
duration = time.time() - start_time
log_to_db(path, duration, error)
handler = SessionHandler(
session_dir, log_config,
on_session_created=notify_created,
on_session_exit=on_exit,
on_before_prune=archive_sessions,
on_session_error=lambda exc: alert_oncall(exc),
)
| Hook | Signature | When |
|---|---|---|
on_session_created |
(path: Path) -> None |
After directory created and logging set up |
on_session_exit |
(path: Path, error: Exception | None) -> None |
When context exits, before pruning |
on_before_prune |
(dirs: list[Path]) -> None |
Before old sessions are deleted |
on_session_error |
(error: Exception) -> None |
When an exception occurs in context |
All hooks are optional (default None). A broken hook is logged as a
warning and never crashes the session.
Key Classes
| Class | Purpose |
|---|---|
SessionDir |
Creates uniquely-named session directories with cleanup policies (by count and age) |
WorkDir |
Manages a user-specified directory without auto-naming or cleanup |
SessionHandler |
Context manager combining SessionDir + LogConfig for full session lifecycle |
LogConfig |
Logging configuration with multi-source resolution (args > env > defaults) |
Configuration Priority
All configurable values follow this resolution order:
- Direct constructor arguments (highest priority)
- Environment variables (with optional prefix)
- Default values (lowest priority)
Environment Variables
All environment variable names follow the pattern {env_prefix}SESSION_DIR_*
or {env_prefix}SESSION_LOG_*. The env_prefix is set via the constructor
(default: empty string).
SessionDir
| Variable | Type | Default | Description |
|---|---|---|---|
SESSION_DIR_PREFIX |
str | session_ |
Prefix for session directory names |
SESSION_DIR_TIMESTAMP_FORMAT |
str | %Y-%m-%d-%H-%M-%S |
strftime format for directory timestamp |
SESSION_DIR_MAX_SESSION_DIRS |
int | 20 |
Maximum session directories to keep (-1 = unlimited) |
SESSION_DIR_MAX_AGE_DAYS |
int | 10 |
Maximum age in days before deletion (-1 = unlimited) |
LogConfig
| Variable | Type | Default | Description |
|---|---|---|---|
SESSION_LOG_FILE_PATH |
path | None |
Log file path (relative or absolute). None disables file logging. |
SESSION_LOG_LEVEL |
str | warning |
Minimum log level (debug/info/warning/error/critical) |
SESSION_LOG_CONSOLE_ENABLED |
bool | false |
Duplicate logs to stdout/stderr |
SESSION_LOG_COLOR_ENABLED |
bool | false |
Enable ANSI color codes in console output |
SESSION_LOG_MESSAGE_FORMAT |
str | (none) | Custom log message format string |
With a prefix like env_prefix="MYAPP_", variables become
MYAPP_SESSION_DIR_PREFIX, MYAPP_SESSION_LOG_LEVEL, etc.
Logging
The package uses vcti.logging for two distinct purposes:
1. Internal operational logging
The package logs its own operations (directory created, pruning started,
errors encountered) via a standard logger at debug/verbose/warning
levels. This is always active and controlled via Python's standard
logging configuration — set the level on the vcti.session logger
namespace to see or suppress these messages.
2. User session logging (via LogConfig)
LogConfig optionally configures file and console logging for the
user's session. This is fully opt-in:
# Batch mode — no logging setup (default)
handler = SessionHandler(session_dir)
# File logging only
handler = SessionHandler(session_dir, LogConfig(file_path="app.log"))
# Console only (interactive use)
handler = SessionHandler(session_dir, LogConfig(console_enabled=True))
# Both file and console
handler = SessionHandler(
session_dir,
LogConfig(
file_path="logs/app.log",
console_enabled=True,
color_enabled=True,
level="debug",
),
)
# Skip LogConfig entirely — handle logging via hooks
handler = SessionHandler(
session_dir,
on_session_created=lambda path: my_custom_logging_setup(path),
)
When log_config is None (the default), no file handlers are created,
no log directories are created, and no console handlers are configured.
The session directory is still created and managed normally.
When file_path is set as a relative path (e.g., "logs/app.log"), it
is resolved relative to the session directory, and the parent directories
are created automatically. Absolute paths are used as-is.
Thread Safety
By default, SessionHandler and WorkDir call os.chdir() to change the
process working directory. This is not thread-safe — os.chdir() affects
the entire process.
For multi-threaded applications, set change_directory=False:
# Thread-safe: cwd is never changed
handler = SessionHandler(session_dir, log_config, change_directory=False)
with handler.session_context() as session:
# Use session.path directly instead of relying on cwd
output_file = session.path / "results.json"
output_file.write_text('{"status": "ok"}')
The same parameter is available on WorkDir:
work_dir = WorkDir(
directory="/shared/work",
log_config=log_config,
change_directory=False,
)
with work_dir.work_context() as wd:
data_file = wd.path / "data.csv"
When to use which:
| Scenario | change_directory |
|---|---|
| Single-threaded scripts | True (default) — simpler, relative paths work naturally |
| Multi-threaded applications | False — use session.path for all file operations |
| Async applications | False — os.chdir() is not async-safe |
Public API
| Symbol | Purpose |
|---|---|
SessionDir |
Session directory creation and pruning |
WorkDir |
User-specified directory management |
SessionHandler |
Full session lifecycle context manager |
LogConfig |
Logging configuration model |
Documentation
- Design — Architecture decisions and configuration model
- Source Guide — File descriptions and execution flows
- API Reference — Autodoc for all modules
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file vcti_session-1.0.1.tar.gz.
File metadata
- Download URL: vcti_session-1.0.1.tar.gz
- Upload date:
- Size: 22.7 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
d831a881941714e767771d1ab854c7501a6b0a13573a3f17dafb4043a48cddad
|
|
| MD5 |
f87101a39bc4e3b86bb4ab50659558ee
|
|
| BLAKE2b-256 |
bdc80c56083b5a65d85d25cc185d3e7a4c5a0df0bc41ec9583dc3b0d1a7d7c99
|
Provenance
The following attestation bundles were made for vcti_session-1.0.1.tar.gz:
Publisher:
publish.yml on vcollab/vcti-python-session
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
vcti_session-1.0.1.tar.gz -
Subject digest:
d831a881941714e767771d1ab854c7501a6b0a13573a3f17dafb4043a48cddad - Sigstore transparency entry: 1187637176
- Sigstore integration time:
-
Permalink:
vcollab/vcti-python-session@39668b84691d2bb88d10a0746dfe98a1543c1601 -
Branch / Tag:
refs/heads/main - Owner: https://github.com/vcollab
-
Access:
private
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@39668b84691d2bb88d10a0746dfe98a1543c1601 -
Trigger Event:
workflow_dispatch
-
Statement type:
File details
Details for the file vcti_session-1.0.1-py3-none-any.whl.
File metadata
- Download URL: vcti_session-1.0.1-py3-none-any.whl
- Upload date:
- Size: 16.8 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
0857e162b79b825fabf12854599aece7e7f70fcec6e64863a3030870dd7adb0a
|
|
| MD5 |
85861b1b4438c213f9f5232151a7ee55
|
|
| BLAKE2b-256 |
11d2c35acf5a303ef8fc5f25b71278cf3a6e81f67f9ddf2d384859376e3c5283
|
Provenance
The following attestation bundles were made for vcti_session-1.0.1-py3-none-any.whl:
Publisher:
publish.yml on vcollab/vcti-python-session
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
vcti_session-1.0.1-py3-none-any.whl -
Subject digest:
0857e162b79b825fabf12854599aece7e7f70fcec6e64863a3030870dd7adb0a - Sigstore transparency entry: 1187637178
- Sigstore integration time:
-
Permalink:
vcollab/vcti-python-session@39668b84691d2bb88d10a0746dfe98a1543c1601 -
Branch / Tag:
refs/heads/main - Owner: https://github.com/vcollab
-
Access:
private
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@39668b84691d2bb88d10a0746dfe98a1543c1601 -
Trigger Event:
workflow_dispatch
-
Statement type: