PolicyEngine Python interface¶
Welcome to the documentation for PolicyEngine, a Python package for analyzing tax-benefit policies and estimating their societal impacts.
Overview¶
This package enables users to create and simulate different scenarios of specific or representative households in a country, under different tax-benefit rules or economic assumptions.
We currently support the UK and the US.
Quick start¶
To install the package, run:
pip install policyengine
Then, for example:
from policyengine import Simulation
sim = Simulation(
scope="macro",
country="uk",
time_period=2025,
reform={
"gov.hmrc.income_tax.allowances.personal_allowance.amount": 15000
},
)
sim.calculate_economy_comparison()
/opt/hostedtoolcache/Python/3.11.12/x64/lib/python3.11/site-packages/tqdm/auto.py:21: TqdmWarning: IProgress not found. Please update jupyter and ipywidgets. See https://ipywidgets.readthedocs.io/en/stable/user_install.html
from .autonotebook import tqdm as notebook_tqdm
No data provided, using default dataset: gs://policyengine-uk-data-private/enhanced_frs_2022_23.h5
Downloading enhanced_frs_2022_23.h5 from bucket policyengine-uk-data-private
INFO:root:Using Google Cloud Storage for download.
---------------------------------------------------------------------------
DefaultCredentialsError Traceback (most recent call last)
Cell In[1], line 3
1 from policyengine import Simulation
----> 3 sim = Simulation(
4 scope="macro",
5 country="uk",
6 time_period=2025,
7 reform={
8 "gov.hmrc.income_tax.allowances.personal_allowance.amount": 15000
9 },
10 )
12 sim.calculate_economy_comparison()
File ~/work/policyengine.py/policyengine.py/policyengine/simulation.py:109, in Simulation.__init__(self, **options)
105 if not isinstance(self.options.data, dict) and not isinstance(
106 self.options.data, Dataset
107 ):
108 logging.debug("Loading data")
--> 109 self._set_data(self.options.data)
110 logging.info("Data loaded")
111 self._initialise_simulations()
File ~/work/policyengine.py/policyengine.py/policyengine/simulation.py:171, in Simulation._set_data(self, file_address)
166 version = None
168 else:
169 # All official PolicyEngine datasets are stored in GCS;
170 # load accordingly
--> 171 filename, version = self._set_data_from_gs(file_address)
172 self.data_version = version
174 time_period = self._set_data_time_period(file_address)
File ~/work/policyengine.py/policyengine.py/policyengine/simulation.py:405, in Simulation._set_data_from_gs(self, file_address)
401 version = self.options.data_version
403 print(f"Downloading {filename} from bucket {bucket}", file=sys.stderr)
--> 405 filepath, version = download(
406 filepath=filename,
407 gcs_bucket=bucket,
408 version=version,
409 return_version=True,
410 )
412 return filename, version
File ~/work/policyengine.py/policyengine.py/policyengine/utils/data_download.py:17, in download(filepath, gcs_bucket, version, return_version)
10 def download(
11 filepath: str,
12 gcs_bucket: str,
13 version: Optional[str] = None,
14 return_version: bool = False,
15 ) -> Tuple[str, str] | str:
16 logging.info("Using Google Cloud Storage for download.")
---> 17 downloaded_version = download_file_from_gcs(
18 bucket_name=gcs_bucket,
19 file_name=filepath,
20 destination_path=filepath,
21 version=version,
22 )
23 if return_version:
24 return filepath, downloaded_version
File ~/work/policyengine.py/policyengine.py/policyengine/utils/google_cloud_bucket.py:41, in download_file_from_gcs(bucket_name, file_name, destination_path, version)
23 def download_file_from_gcs(
24 bucket_name: str,
25 file_name: str,
26 destination_path: str,
27 version: Optional[str] = None,
28 ) -> str | None:
29 """
30 Download a file from Google Cloud Storage to a local path.
31
(...)
38 version (str): The version of the file that was downloaded, if available.
39 """
---> 41 version = _get_client().download(
42 bucket_name,
43 file_name,
44 Path(destination_path),
45 version=version,
46 return_version=True,
47 )
48 return version
File ~/work/policyengine.py/policyengine.py/policyengine/utils/google_cloud_bucket.py:14, in _get_client()
12 if _caching_client is not None:
13 return _caching_client
---> 14 _caching_client = CachingGoogleStorageClient()
15 return _caching_client
File ~/work/policyengine.py/policyengine.py/policyengine/utils/data/caching_google_storage_client.py:19, in CachingGoogleStorageClient.__init__(self)
18 def __init__(self):
---> 19 self.client = SimplifiedGoogleStorageClient()
20 self.cache = diskcache.Cache()
File ~/work/policyengine.py/policyengine.py/policyengine/utils/data/simplified_google_storage_client.py:19, in SimplifiedGoogleStorageClient.__init__(self)
18 def __init__(self):
---> 19 self.client = Client()
File /opt/hostedtoolcache/Python/3.11.12/x64/lib/python3.11/site-packages/google/cloud/storage/client.py:247, in Client.__init__(self, project, credentials, _http, client_info, client_options, use_auth_w_custom_endpoint, extra_headers, api_key)
244 no_project = True
245 project = "<none>"
--> 247 super(Client, self).__init__(
248 project=project,
249 credentials=credentials,
250 client_options=client_options,
251 _http=_http,
252 )
254 # Validate that the universe domain of the credentials matches the
255 # universe domain of the client.
256 if self._credentials.universe_domain != self.universe_domain:
File /opt/hostedtoolcache/Python/3.11.12/x64/lib/python3.11/site-packages/google/cloud/client/__init__.py:338, in ClientWithProject.__init__(self, project, credentials, client_options, _http)
337 def __init__(self, project=None, credentials=None, client_options=None, _http=None):
--> 338 _ClientProjectMixin.__init__(self, project=project, credentials=credentials)
339 Client.__init__(
340 self, credentials=credentials, client_options=client_options, _http=_http
341 )
File /opt/hostedtoolcache/Python/3.11.12/x64/lib/python3.11/site-packages/google/cloud/client/__init__.py:286, in _ClientProjectMixin.__init__(self, project, credentials)
283 project = getattr(credentials, "project_id", None)
285 if project is None:
--> 286 project = self._determine_default(project)
288 if project is None:
289 raise EnvironmentError(
290 "Project was not passed and could not be "
291 "determined from the environment."
292 )
File /opt/hostedtoolcache/Python/3.11.12/x64/lib/python3.11/site-packages/google/cloud/client/__init__.py:305, in _ClientProjectMixin._determine_default(project)
302 @staticmethod
303 def _determine_default(project):
304 """Helper: use default project detection."""
--> 305 return _determine_default_project(project)
File /opt/hostedtoolcache/Python/3.11.12/x64/lib/python3.11/site-packages/google/cloud/_helpers/__init__.py:152, in _determine_default_project(project)
140 """Determine default project ID explicitly or implicitly as fall-back.
141
142 See :func:`google.auth.default` for details on how the default project
(...)
149 :returns: Default project if it can be determined.
150 """
151 if project is None:
--> 152 _, project = google.auth.default()
153 return project
File /opt/hostedtoolcache/Python/3.11.12/x64/lib/python3.11/site-packages/google/auth/_default.py:685, in default(scopes, request, quota_project_id, default_scopes)
677 _LOGGER.warning(
678 "No project ID could be determined. Consider running "
679 "`gcloud config set project` or setting the %s "
680 "environment variable",
681 environment_vars.PROJECT,
682 )
683 return credentials, effective_project_id
--> 685 raise exceptions.DefaultCredentialsError(_CLOUD_SDK_MISSING_CREDENTIALS)
DefaultCredentialsError: Your default credentials were not found. To set up Application Default Credentials, see https://cloud.google.com/docs/authentication/external/set-up-adc for more information.