Main Client¶
The pybdl.client.BDL class is the main entry point for the library. It
provides two interfaces for accessing BDL data:
- Access Layer (default, recommended): Returns pandas DataFrames -
use
bdl.levels,bdl.data, etc. - API Layer: Returns raw dictionaries - use
bdl.api.levels,bdl.api.data, etc.
For most users, the access layer is recommended as it provides DataFrames that are immediately ready for data analysis.
Access Layer (Default Interface)¶
The access layer is the primary interface and returns pandas DataFrames:
from pybdl import BDL, BDLConfig
bdl = BDL(BDLConfig(api_key="your-api-key"))
# Access layer - returns DataFrames
levels_df = bdl.levels.list_levels()
variables_df = bdl.variables.list_variables()
data_df = bdl.data.get_data_by_variable(variable_id="3643", years=[2021])
# Data is ready for pandas operations
print(levels_df.head())
print(data_df.dtypes)
print(data_df.columns)
Key features of the access layer:
- Automatic DataFrame conversion: All responses are pandas DataFrames
- Column normalization: camelCase → snake_case (e.g.,
variableId→variable_id) - Data type inference: Proper types (integers, floats, booleans)
- Nested data flattening: Complex structures are normalized into tabular format
See access layer for comprehensive documentation on the access layer.
API Layer (Low-Level Interface)¶
The API layer provides direct access to raw API responses as dictionaries:
from pybdl import BDL
bdl = BDL()
# API layer - returns raw dictionaries
levels_data = bdl.api.levels.list_levels()
data_dict = bdl.api.data.get_data_by_variable(variable_id="3643", years=[2021])
# Raw API response structure
print(type(levels_data)) # list
print(type(data_dict)) # list or dict
Use the API layer when you need:
- Raw API response structure
- Custom response processing
- Direct access to API metadata
- Integration with non-pandas workflows
See api clients for details about the API layer.
Examples¶
Basic Usage with Access Layer¶
from pybdl import BDL, BDLConfig
# Initialize client
bdl = BDL(BDLConfig(api_key="your-api-key"))
# Get administrative levels
levels = bdl.levels.list_levels()
print(f"Found {len(levels)} administrative levels")
# Get variables
variables = bdl.variables.search_variables(name="population")
print(f"Found {len(variables)} population variables")
# Get data
data = bdl.data.get_data_by_variable("3643", years=[2021], unit_level=2)
print(f"Retrieved {len(data)} data points")
print(data.head())
Using Both Interfaces¶
from pybdl import BDL
bdl = BDL()
# Access layer for DataFrame analysis
df = bdl.data.get_data_by_variable("3643", years=[2021])
avg_value = df['val'].mean()
# API layer for raw metadata
metadata = bdl.api.data.get_data_by_variable(
"3643", years=[2021], return_metadata=True
)
if isinstance(metadata, tuple):
data, meta = metadata
print(f"Total pages: {meta.get('totalPages', 'unknown')}")
Context Manager and Session Lifecycle¶
BDL can be used as a context manager to ensure HTTP sessions and
underlying resources are properly closed when you are done. This is
especially important in long-running processes and scripts that should
not leave open connections behind.
from pybdl import BDL, BDLConfig
# Context manager — sessions are closed automatically on exit
with BDL(BDLConfig(api_key="your-api-key")) as bdl:
levels = bdl.levels.list_levels()
data = bdl.data.get_data_by_variable("3643", years=[2021])
When not using the context manager, call bdl.close() explicitly
when finished:
The async interface supports async with:
import asyncio
from pybdl import BDL
async def main():
async with BDL() as bdl:
data = await bdl.data.aget_data_by_variable("3643", years=[2021])
return data
asyncio.run(main())
Async Usage¶
Both interfaces support async operations:
import asyncio
from pybdl import BDL
async def main():
bdl = BDL()
# Async access layer
levels_df = await bdl.levels.alist_levels()
variables_df = await bdl.variables.alist_variables()
# Async API layer
levels_data = await bdl.api.levels.alist_levels()
return levels_df, variables_df, levels_data
asyncio.run(main())
API reference¶
client ¶
APINamespace
dataclass
¶
APINamespace(
aggregates,
attributes,
data,
levels,
measures,
subjects,
units,
variables,
version,
years,
)
Typed namespace for low-level API clients.
BDL ¶
Main interface for interacting with the Local Data Bank (BDL) API.
This class provides a unified entry point to all BDL API endpoints, including aggregates, attributes, data, levels, measures, subjects, units, variables, version, and years.
The access layer (default interface) returns pandas DataFrames with proper column labels and data types. The API layer (via .api) returns raw dictionaries for advanced use cases.
Initialize the BDL client and all API endpoint namespaces.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
config
|
BDLConfig | dict | None
|
BDLConfig instance or dict. If not provided, configuration is loaded from environment variables and defaults. |
None
|
Raises:
| Type | Description |
|---|---|
TypeError
|
If config is not a dict, BDLConfig, or None. |
Note
Configuration can be set through: 1. Direct parameter passing to BDLConfig 2. Environment variables (BDL_API_KEY, BDL_LANGUAGE, etc.) 3. Default values
Source code in pybdl/client.py
api
instance-attribute
¶
api = APINamespace(
aggregates=AggregatesAPI(config),
attributes=AttributesAPI(config),
data=DataAPI(config),
levels=LevelsAPI(config),
measures=MeasuresAPI(config),
subjects=SubjectsAPI(config),
units=UnitsAPI(config),
variables=VariablesAPI(config),
version=VersionAPI(config),
years=YearsAPI(config),
)
close ¶
Close all synchronous HTTP resources owned by the client.
aclose
async
¶
Close all synchronous and asynchronous HTTP resources owned by the client.
Source code in pybdl/client.py
__enter__ ¶
__exit__ ¶
__aenter__
async
¶
Seealso