AI_MRI / scripts /validation /read_pkl.py
DeboraJ1's picture
add read_pkl.py, update: metrics.py includes subgroup based metric
0cf9b4c
Raw History Blame Contribute Delete
2.99 kB
"""Inspect pickle files in a directory.
Pickle files can contain arbitrary Python objects, so only open files you trust.
"""
from __future__ import annotations
import argparse
import pickle
from collections.abc import Mapping, Sequence
from pathlib import Path
from typing import Any
def _short_repr(value: Any, limit: int = 200) -> str:
text = repr(value).replace("\n", "\\n")
return text if len(text) <= limit else f"{text[: limit - 3]}..."
def _describe(value: Any, *, max_items: int, indent: int = 0) -> list[str]:
"""Return a readable, bounded description of a pickled object."""
prefix = " " * indent
lines = [f"{prefix}type: {type(value).__module__}.{type(value).__qualname__}"]
if hasattr(value, "shape"):
lines.append(f"{prefix}shape: {value.shape}")
if hasattr(value, "dtype"):
lines.append(f"{prefix}dtype: {value.dtype}")
if isinstance(value, Mapping):
lines.append(f"{prefix}length: {len(value)}")
for index, (key, item) in enumerate(value.items()):
if index >= max_items:
lines.append(f"{prefix}... ({len(value) - max_items} more items)")
break
lines.append(f"{prefix}{_short_repr(key)}:")
lines.extend(_describe(item, max_items=max_items, indent=indent + 2))
elif isinstance(value, Sequence) and not isinstance(value, (str, bytes, bytearray)):
lines.append(f"{prefix}length: {len(value)}")
for index, item in enumerate(value[:max_items]):
lines.append(f"{prefix}[{index}]:")
lines.extend(_describe(item, max_items=max_items, indent=indent + 2))
if len(value) > max_items:
lines.append(f"{prefix}... ({len(value) - max_items} more items)")
else:
lines.append(f"{prefix}value: {_short_repr(value)}")
return lines
def inspect_file(path: Path, *, max_items: int) -> None:
"""Load and print one pickle file."""
print(f"\n=== {path} ===")
try:
with path.open("rb") as file:
value = pickle.load(file)
except Exception as error: # A bad file should not stop inspection of other files.
print(f"ERROR: {type(error).__name__}: {error}")
return
print("\n".join(_describe(value, max_items=max_items)))
def main() -> None:
parser = argparse.ArgumentParser(description=__doc__)
parser.add_argument("directory", type=Path, help="Directory containing pickle files")
parser.add_argument(
"-r",
"--recursive",
action="store_true",
help="Search for pickle files in subdirectories too",
)
parser.add_argument(
"--max-items",
type=int,
default=10,
help="Maximum mapping/sequence items to show per object (default: 10)",
)
args = parser.parse_args()
if not args.directory.is_dir():
parser.error(f"not a directory: {args.directory}")
if args.max_items < 1:
parser.error("--max-items must be at least 1")
pattern = "**/*.pkl" if args.recursive else "*.pkl"
paths = sorted(args.directory.glob(pattern))
if not paths:
print(f"No .pkl files found in {args.directory}")
return
for path in paths:
inspect_file(path, max_items=args.max_items)
if __name__ == "__main__":
main()