Python SDK User Guide
This guide is for Planet SDK for Python users who want to use Python code to search, order, customize, and deliver Planet imagery and data. If you’re new to Python, you may want to choose the no-code option of using the command-line interface (CLI). But if you’ve successfully followed the instructions to get started and you’re ready to try your hand at Python coding, this guide should be all you need to use this SDK to get Planet data.
We want to hear from you!
This is a beta release. We encourage you to test your workflows rigorously. Based on your feedback, we may roll out additional updates to improve your experience. Please share your feedback with us on our Planet Developers community channel.
This guide walks you through the steps:
- Create a session—set up a context for calling on Planet servers and receiving data back.
- Authenticate—pass your API key to Planet services to verify your permissions to data.
- Create an orderbuild an orders client, send the request within the session context, and download it when it’s ready.
- Collect and list data—handle the potentially large number of results from a search for imagery.
- Query the data catalog—search the catalog based on a filter, activate the assets you want, and download and validate it when it’s ready.
Create a session¶
Communication with the Planet services is provided with the Session
class.
The recommended way to use a Session
is as a context manager. This will
provide for automatic clean up of connections when the context is left.
import asyncio
import os
from planet import Session
async def main():
async with Session() as sess:
# perform operations here
pass
asyncio.run(main())
Alternatively, use await Session.aclose()
to close a Session
explicitly:
async def main():
sess = Session()
# perform operations here
await sess.aclose()
asyncio.run(main())
Authenticate with Planet services¶
A Session
requires authentication to communicate with Planet services. This
authentication information is retrieved when a Session
is created. By default,
a Session
obtains authorization from the following sources with order
indicating priority:
- The environment variable
PL_API_KEY
- The secret file
The SDK provides the auth.Auth
class for managing authentication information.
This module can be used to obtain authentication information from username
and password with Auth.from_login()
. Additionally, it can be created with
the API key obtained directly from the Planet account site with Auth.from_key(<API_KEY>)
.
Once the authentication information is obtained, the most convenient way of
managing it for local use is to write it to a secret file using Auth.write()
.
It can also be accessed, e.g. to store in an environment variable, as
Auth.value
.
For example, to obtain and store authentication information:
import getpass
from planet import Auth
pw = getpass.getpass()
auth = Auth.from_login('user', 'pw')
auth.store()
The default authentication behavior of the Session
can be modified by specifying
Auth
explicitly using the methods Auth.from_file()
and Auth.from_env()
.
While Auth.from_key()
and Auth.from_login
can be used, it is recommended
that those functions be used in authentication initialization and the
authentication information be stored using Auth.store()
.
The file and environment variable read from can be customized in the respective functions. For example, authentication can be read from a custom environment variable:
import asyncio
import os
from planet import Auth, Session
auth = Auth.from_env('ALTERNATE_VAR')
async def main():
async with Session(auth=auth) as sess:
# perform operations here
pass
asyncio.run(main())
Create an order¶
The Orders Client mostly mirrors the Orders API, with the only difference being the addition of the ability to poll for when an order is completed and to download an entire order.
async def main():
async with Session() as sess:
client = sess.client('orders')
# perform operations here
asyncio.run(main())
Your orders client¶
When creating an order, the order request details must be provided to the API
as a JSON blob. This JSON blob can be built up manually or by using the
build_request
function.
An example of creating the request JSON with build_request
:
from planet import order_request
products = [
order_request.product(['20170614_113217_3163208_RapidEye-5'],
'analytic', 'REOrthoTile')
]
tools = [
order_request.toar_tool(scale_factor=10000),
order_request.reproject_tool(projection='WSG84', kernel='cubic'),
order_request.tile_tool(1232, origin_x=-180, origin_y=-90,
pixel_size=0.000027056277056,
name_template='C1232_30_30_{tilex:04d}_{tiley:04d}')
]
request = order_request.build_request(
'test_order', products=products, tools=tools)
The same thing, expressed as a JSON
blob:
request = {
"name": "test_order",
"products": [
{
"item_ids": [
"20170614_113217_3163208_RapidEye-5"
],
"item_type": "REOrthoTile",
"product_bundle": "analytic"
}
],
"tools": [
{
"toar": {
"scale_factor": 10000
}
},
{
"reproject": {
"projection": "WSG84",
"kernel": "cubic"
}
},
{
"tile": {
"tile_size": 1232,
"origin_x": -180,
"origin_y": -90,
"pixel_size": 2.7056277056e-05,
"name_template": "C1232_30_30_{tilex:04d}_{tiley:04d}"
}
}
]
}
Once the order request is built up, creating an order is done within
the context of a Session
with the OrdersClient
:
async def main():
async with Session() as sess:
cl = sess.client('orders')
order = await cl.create_order(request)
asyncio.run(main())
Waiting and downloading an order¶
Once an order is created, the Orders API takes some time to create the order and thus we must wait a while before downloading the order. We can use waiting to watch the order creation process and find out when the order is created successfully and ready to download.
With wait and download, it is often desired to track progress as these
processes can take a long time. Therefore, in this example, we use a progress
bar from the reporting
module to report wait status. download_order
has
reporting built in.
from planet import reporting
async def create_wait_and_download():
async with Session() as sess:
cl = sess.client('orders')
with reporting.StateBar(state='creating') as bar:
# create order
order = await cl.create_order(request)
bar.update(state='created', order_id=order['id'])
# poll
await cl.wait(order['id'], callback=bar.update_state)
# download
await cl.download_order(order['id'])
asyncio.run(create_poll_and_download())
Validating checksums¶
Checksum validation provides for verification that the files in an order have been downloaded successfully and are not missing, corrupted, or changed. This functionality is included in the OrderClient, but does not require an instance of the class to be used.
To perform checksum validation:
from pathlib import Path
# path includes order id
order_path = Path('193e5bd1-dedc-4c65-a539-6bc70e55d928')
OrdersClient.validate_checksum(order_path, 'md5')
Collecting results¶
Some API calls, such as searching for imagery and listing orders, return a
varying, and potentially large, number of results. These API responses are
paged. The SDK manages paging internally and the associated client commands
return an asynchronous iterator over the results. These results can be
converted to a JSON blob using the collect
command. When the results
represent GeoJSON features, the JSON blob is a GeoJSON FeatureCollection.
Otherwise, the JSON blob is a list of the individual results.
import asyncio
from planet import collect, Session
async def main():
async with Session() as sess:
client = sess.client('orders')
orders_list = collect(client.list_orders())
asyncio.run(main())
Alternatively, these results can be converted to a list directly with
orders_list = [o async for o in client.list_orders()]
Query the data catalog¶
The Data Client mostly mirrors the Data API, with the only difference being the addition of functionality to activate an asset, poll for when activation is complete, and download the asset.
async def main():
async with Session() as sess:
client = sess.client('data')
# perform operations here
asyncio.run(main())
Filter¶
When performing a quick search, creating or updating a saved search, or
requesting stats, the data search filter must be provided to the API
as a JSON blob. This JSON blob can be built up manually or by using the
data_filter
module.
An example of creating the request JSON with data_filter
:
from datetime import datetime
from planet import data_filter
sfilter = data_filter.and_filter([
data_filter.permission_filter(),
data_filter.date_range_filter('acquired', gt=datetime(2022, 6, 1, 1))
])
The same thing, expressed as a JSON
blob:
sfilter = {
'type': 'AndFilter',
'config': [
{'type': 'PermissionFilter', 'config': ['assets:download']},
{
'type': 'DateRangeFilter',
'field_name': 'acquired',
'config': {'gt': '2022-06-01T01:00:00Z'}
}
]
}
Once the filter is built up, performing a search is done within
the context of a Session
with the DataClient
:
async def main():
async with Session() as sess:
cl = sess.client('data')
items = [i async for i in cl.search(['PSScene'], sfilter)]
asyncio.run(main())
Downloading an asset¶
Downloading an asset is a multi-step process involving: activating the asset, waiting for the asset to be active, downloading the asset, and, optionally, validating the downloaded file.
With wait and download, it is often desired to track progress as these
processes can take a long time. Therefore, in this example, we use a simple
print command to report wait status. download_asset
has reporting built in.
async def download_and_validate():
async with Session() as sess:
cl = sess.client('data')
# get asset description
item_type_id = 'PSScene'
item_id = '20221003_002705_38_2461'
asset_type_id = 'ortho_analytic_4b'
asset = await cl.get_asset(item_type_id, item_id, asset_type_id)
# activate asset
await cl.activate_asset(asset)
# wait for asset to become active
asset = await cl.wait_asset(asset, callback=print)
# download asset
path = await cl.download_asset(asset)
# validate download file
cl.validate_checksum(asset, path)