Debugging and Troubleshooting
Relevant source files
The following files were used as context for generating this wiki page: - [CHANGELOG.md](https://github.com/przkos/picamera2/blob/HEAD/CHANGELOG.md) - [README.md](https://github.com/przkos/picamera2/blob/HEAD/README.md) - [apps/app_full.py](https://github.com/przkos/picamera2/blob/HEAD/apps/app_full.py) - [picamera2/picamera2.py](https://github.com/przkos/picamera2/blob/HEAD/picamera2/picamera2.py) - [picamera2/request.py](https://github.com/przkos/picamera2/blob/HEAD/picamera2/request.py) - [tests/test_list.txt](https://github.com/przkos/picamera2/blob/HEAD/tests/test_list.txt) - [tools/checkstyle.py](https://github.com/przkos/picamera2/blob/HEAD/tools/checkstyle.py) - [tools/run_tests.py](https://github.com/przkos/picamera2/blob/HEAD/tools/run_tests.py)The picamera2 library provides several mechanisms for debugging and troubleshooting, ranging from built-in logging and automated testing to real-time metadata analysis. These tools are essential for diagnosing issues related to camera configuration, performance, and image quality. Understanding these features can help developers identify the root cause of problems, from initialization failures to unexpected runtime behavior.
This guide covers the primary debugging tools and techniques available in the project, including the logging framework, the automated test suite, code style checkers, and methods for inspecting live camera metadata. It also references common issues and fixes documented in the project's change log.
Logging
The Picamera2 class includes a static method for configuring logging, which is a fundamental tool for debugging applications.
Sources: picamera2/picamera2.py:165-188
Enabling Logging
Logging can be enabled and configured using the Picamera2.set_logging static method. This allows you to control the verbosity and output destination of log messages.
from picamera2 import Picamera2
import logging
# Set logging level to INFO
Picamera2.set_logging(Picamera2.INFO)
# Or for more detailed output
Picamera2.set_logging(Picamera2.DEBUG)
Sources: picamera2/picamera2.py:165-171
Logging Levels
The library exposes standard Python logging levels as class attributes.
| Level | Description |
|---|---|
Picamera2.DEBUG | Detailed information, typically of interest only when diagnosing problems. |
Picamera2.INFO | Confirmation that things are working as expected. |
Picamera2.WARNING | An indication that something unexpected happened, or indicative of some problem in the near future. |
Picamera2.ERROR | Due to a more serious problem, the software has not been able to perform some function. |
Picamera2.CRITICAL | A serious error, indicating that the program itself may be unable to continue running. |
Sources: picamera2/picamera2.py:160-164
Customizing Log Output
The set_logging method also accepts parameters to customize the output stream and message format.
import sys
# Log to stderr with a custom message format
Picamera2.set_logging(level=Picamera2.DEBUG, output=sys.stderr, msg="%(levelname)s: %(message)s")
Sources: picamera2/picamera2.py:169-188
Automated Testing
The repository includes a suite of automated tests and a script to execute them. This is the first line of defense for identifying regressions and ensuring stability.
Sources: tools/run_tests.py, tests/test_list.txt
Running Tests
Tests are executed using the tools/run_tests.py script. It reads a list of test files and runs them sequentially, reporting the status of each.
# Run all tests from the default test list
./tools/run_tests.py
Sources: README.md:83-85, tools/run_tests.py:100-110
The script accepts arguments to specify the test directory, the picamera2 source directory, and the test list files.
Sources: tools/run_tests.py:137-144
Test Execution Flow
The run_tests.py script follows a clear execution path for each test, including cleaning the test directory, running the test with a timeout, and parsing the output for status keywords.
The diagram below illustrates the test execution flow managed by run_tests.py.
Sources: tools/run_tests.py:73-134
Test Outcomes
The script reports one of the following outcomes for each test:
| Outcome | Description |
|---|---|
PASSED | The test script exited with code 0 and no "error" strings were found in its output. |
FAILED | The test script exited with a non-zero exit code. |
ERROR | The test script exited with code 0, but an "error" string was detected in its output. |
TIMED OUT | The test did not complete within the 90-second timeout. |
SKIPPED | The test script reported that it was skipped. |
Sources: tools/run_tests.py:108-134
Code Style and Static Analysis
To maintain code quality and prevent common errors, picamera2 uses several code checking tools, which can be run manually or via a pre-commit hook.
Sources: tools/checkstyle.py, README.md:92-100
checkstyle.py
The tools/checkstyle.py script is a comprehensive style and format checker based on libcamera's utility. It performs several checks:
- Formatting: Uses
clang-formatfor C/C++ files. - Python Style: Uses
pycodestyleto check for PEP 8 compliance. - Shell Scripts: Uses
shellcheckto validate shell scripts. - Trailing Whitespace: Strips trailing whitespace from various file types.
The script can be run on a git revision range, staged changes, or an amendment to the previous commit.
Sources: tools/checkstyle.py:1-15, tools/checkstyle.py:408-417, tools/checkstyle.py:530-544
Pre-commit Hook
The repository recommends using a pre-commit hook to automate linting before committing changes. This helps catch issues early. The hook can be installed using pip and pre-commit.
pip3 install pre-commit
pre-commit install
This setup uses flake8 to perform linting on changed files.
Sources: README.md:92-100
Real-time Metadata Analysis
One of the most powerful debugging techniques is to inspect the metadata of completed camera requests in real-time. This provides insight into the camera's state, including exposure, gain, and color balance settings.
The post_callback Function
The Picamera2 object has a post_callback attribute that can be set to a function. This function is called for every completed request, receiving the CompletedRequest object as an argument.
def post_callback(request):
metadata = request.get_metadata()
print(metadata)
picam2 = Picamera2()
picam2.post_callback = post_callback
# ... configure and start camera
Sources: picamera2/picamera2.py:1200-1206, apps/app_full.py:32-34
The following sequence diagram shows how the post_callback is integrated into the request processing loop.
Sources: picamera2/picamera2.py:1194-1233
Accessing Metadata
The CompletedRequest object provides the get_metadata() method, which returns a dictionary of the frame's metadata. The apps/app_full.py example demonstrates how to extract and display this information.
Key metadata fields for debugging include:
ExposureTimeAnalogueGainDigitalGainColourGainsColourCorrectionMatrixFrameDurationAfState(for autofocus)
Sources: apps/app_full.py:36-64, picamera2/request.py:99-104
Here is an example from apps/app_full.py showing how to process metadata:
def post_callback(request):
# Read the metadata we get back from every request
metadata = request.get_metadata()
# ... (sorting and formatting logic) ...
# Set values from the metadata
if not aec_tab.exposure_time.isEnabled():
# Only set if they're disabled
aec_tab.exposure_time.setValue(metadata["ExposureTime"])
aec_tab.analogue_gain.setValue(metadata["AnalogueGain"])
if not aec_tab.colour_gain_r.isEnabled():
# Only set if they're disabled
aec_tab.colour_gain_r.setValue(metadata.get("ColourGains", [1.0, 1.0])[0])
aec_tab.colour_gain_b.setValue(metadata.get("ColourGains", [1.0, 1.0])[1])
vid_tab.frametime = metadata["FrameDuration"]
Sources: apps/app_full.py:32-64
Error Handling and Timeouts
The library includes mechanisms to handle errors during operation and to recover from stalled states.
Initialization and Configuration Errors
- Camera Not Found:
Picamera2will raise aRuntimeErrorduring initialization if no cameras are found, often reminding the user to disable the legacy camera stack.
Sources: picamera2/picamera2.py:500-502 - Invalid Configuration: The
configuremethod performs checks on the camera configuration dictionary. It will raise aRuntimeErrorfor invalid stream parameters, incorrect types, or iflibcamerarejects the configuration.
Sources: picamera2/picamera2.py:910-912, picamera2/picamera2.py:968-973
Asynchronous Operation Timeouts
Methods that can be run asynchronously (e.g., capture_file, capture_request) return a Job object. The wait() method on this job can accept a timeout parameter in seconds. If the operation does not complete within the timeout, an exception is raised.
Sources: picamera2/picamera2.py:1260-1264
Recovering from a Stalled Camera
The CHANGELOG.md mentions improved handling of timeouts when cameras stop responding, including a mechanism for a complete reset. The cancel_all_and_flush() method is provided to clear pending jobs, which is useful for tidying up after an operation has timed out, allowing the camera to be closed cleanly.
Sources: CHANGELOG.md:83-85, picamera2/picamera2.py:1145-1154
Common Issues from Change Log
The CHANGELOG.md file is a valuable resource for understanding past bugs and troubleshooting steps. Some recurring themes include:
| Issue Category | Example Fixes | Relevant Versions |
|---|---|---|
| Memory Leaks | Fixed descriptor leak in DmaAllocator, EGL memory leak, and leak in DmaAllocator during mode switches. | 0.3.18, 0.3.16 |
| Encoder Problems | Fixed V4L2 encoder lock-up, encoders dropping frames when closed, and H264 quality parameter having no effect. | 0.3.26, 0.3.13, 0.3.10 |
| Configuration | Fixed configuration alignment on Pi 5, issues with USB cams, and search path for tuning files. | 0.3.19, 0.3.12, 0.3.11 |
| Asynchronous Calls | Refactored how async calls work, requiring picam2.wait(job) to get results. | 0.3.7 |
| Resource Management | Improved resource freeing on close(), allowing more reliable re-opening of the camera object. | 0.3.6, 0.3.4 |
Sources: CHANGELOG.md