Skip to content

Commit a1ddfa8

Browse files
authored
Merge pull request #221751 from stevemunk/SM-RestSDK-Python
The Azure Maps Python SDK
2 parents 599c0d1 + 57067a4 commit a1ddfa8

File tree

2 files changed

+373
-1
lines changed

2 files changed

+373
-1
lines changed
Lines changed: 372 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,372 @@
1+
---
2+
title: How to create Azure Maps applications using the Python REST SDK (preview)
3+
titleSuffix: Azure Maps
4+
description: How to develop applications that incorporate Azure Maps using the Python SDK Developers Guide.
5+
author: stevemunk
6+
ms.author: v-munksteve
7+
ms.date: 01/15/2021
8+
ms.topic: how-to
9+
ms.service: azure-maps
10+
services: azure-maps
11+
---
12+
13+
# Python REST SDK Developers Guide (preview)
14+
15+
The Azure Maps Python SDK can be integrated with Python applications and libraries to build map-related and location-aware applications. The Azure Maps Python SDK contains APIs for Search, Route, Render and Geolocation. These APIs support operations such as searching for an address, routing between different coordinates, obtaining the geo-location of a specific IP address.
16+
17+
## Prerequisites
18+
19+
- [Azure Maps account][Azure Maps account].
20+
- [Subscription key][Subscription key] or other form of [authentication][authentication].
21+
- Python on 3.7 or later. It's recommended to use the [latest release][python latest release]. For more information, see [Azure SDK for Python version support policy][support policy].
22+
23+
> [!TIP]
24+
> You can create an Azure Maps account programmatically, Here's an example using the Azure CLI:
25+
>
26+
> ```azurecli
27+
> az maps account create --kind "Gen2" --account-name "myMapAccountName" --resource-group "<resource group>" --sku "G2"
28+
> ```
29+
30+
## Create a python project
31+
32+
The following example shows how to create a console program named `demo` with Python:
33+
34+
```powershell
35+
mkdir mapsDemo
36+
cd mapsDemo
37+
New-Item demo.py
38+
```
39+
40+
### Install needed python packages
41+
42+
Each service in Azure Maps is contained in its own package. When using the Azure Maps Python SDK, you can install just the packages of the services you need.
43+
44+
Here we install the Azure Maps Search package. Since it’s still in public preview, you need to add the `--pre` flag: 
45+
46+
```powershell
47+
pip install azure-maps-search --pre
48+
```
49+
50+
### Azure Maps services
51+
52+
Azure Maps Python SDK supports Python version 3.7 or later. For more information on future Python versions, see [Azure SDK for Python version support policy][support policy].
53+
54+
| Service Name  | PyPi package  | Samples  |
55+
|----------------------------|-------------------------|--------------|
56+
| [Search][py search readme] | [azure-maps-search][py search package] | [search samples][py search sample] |
57+
| [Route][py route readme] | [azure-maps-route][py route package] | [route samples][py route sample] |
58+
| [Render][py render readme] | [azure-maps-render][py render package]|[render sample][py render sample] |
59+
| [Geolocation][py geolocation readme]|[azure-maps-geolocation][py geolocation package]|[geolocation sample][py geolocation sample] |
60+
61+
## Create and authenticate a MapsSearchClient
62+
63+
You'll need a `credential` object for authentication when creating the `MapsSearchClient` object used to access the Azure Maps search APIs. You can use either an Azure Active Directory (Azure AD) credential or an Azure subscription key to authenticate. For more information on authentication, see [Authentication with Azure Maps][authentication].
64+
65+
> [!TIP]
66+
> The`MapsSearchClient` is the primary interface for developers using the Azure Maps search library. See [Azure Maps Search package client library][Search package client library] to learn more about the search methods available.
67+
68+
### Using an Azure AD credential
69+
70+
You can authenticate with Azure AD using the [Azure Identity package][Azure Identity package]. To use the [DefaultAzureCredential][defaultazurecredential] provider, you'll need to install the Azure Identity client package:
71+
72+
```powershell
73+
pip install azure-identity
74+
```
75+
76+
You'll need to register the new Azure AD application and grant access to Azure Maps by assigning the required role to your service principal. For more information, see [Host a daemon on non-Azure resources][Host daemon]. During this process you'll get an Application (client) ID, a Directory (tenant) ID, and a client secret. Copy these values and store them in a secure place. You'll need them in the following steps.
77+
78+
Next you'll need to specify the Azure Maps account you intend to use by specifying the maps’ client ID. The Azure Maps account client ID can be found in the Authentication sections of the Azure Maps account. For more information, see [View authentication details][View authentication details].
79+
80+
Set the values of the Application (client) ID, Directory (tenant) ID, and client secret of your Azure AD application, and the map resource’s client ID as environment variables:
81+
82+
| Environment Variable | Description |
83+
|----------------------|---------------------------------------------------------------|
84+
| AZURE_CLIENT_ID | Application (client) ID in your registered application |
85+
| AZURE_CLIENT_SECRET | The value of the client secret in your registered application |
86+
| AZURE_TENANT_ID | Directory (tenant) ID in your registered application |
87+
| MAPS_CLIENT_ID | The client ID in your Azure Map account |
88+
89+
Now you can create environment variables in PowerShell to store these values:
90+
91+
```powershell
92+
$Env:AZURE_CLIENT_ID="Application (client) ID"
93+
$Env:AZURE_CLIENT_SECRET="your client secret"
94+
$Env:AZURE_TENANT_ID="your Directory (tenant) ID"
95+
$Env:MAPS_CLIENT_ID="your Azure Maps client ID"
96+
```
97+
98+
After setting up the environment variables, you can use them in your program to instantiate the `AzureMapsSearch` client. Create a file named *demo.py* and add the following:
99+
100+
```Python
101+
import os
102+
from azure.identity import DefaultAzureCredential
103+
from azure.maps.search import MapsSearchClient
104+
105+
credential = DefaultAzureCredential()
106+
maps_client_id = os.getenv("MAPS_CLIENT_ID")
107+
maps_search_client = MapsSearchClient(
108+
client_id=maps_client_id,
109+
credential=credential
110+
)
111+
```
112+
113+
> [!IMPORTANT]
114+
> The other environment variables created above, while not used in the code sample here, are required by `DefaultAzureCredential()`. If you do not set these environment variables correctly, using the same naming conventions, you will get run-time errors. For example, if your `AZURE_CLIENT_ID` is missing or invalid you will get an `InvalidAuthenticationTokenTenant` error.
115+
116+
### Using a subscription key credential
117+
118+
You can authenticate with your Azure Maps subscription key. Your subscription key can be found in the **Authentication** section in the Azure Maps account as shown in the following screenshot:
119+
120+
:::image type="content" source="./media/rest-sdk-dev-guides/subscription-key.png" alt-text="A screenshot showing the subscription key in the Authentication section of an Azure Maps account." lightbox="./media/rest-sdk-dev-guides/subscription-key.png":::
121+
122+
Now you can create environment variables in PowerShell to store the subscription key:
123+
124+
```powershell
125+
$Env:SUBSCRIPTION_KEY="your subscription key"
126+
```
127+
128+
Once your environment variable is created, you can access it in your code. Create a file named *demo.py* and add the following:
129+
130+
```Python
131+
import os
132+
133+
from azure.core.credentials import AzureKeyCredential
134+
from azure.maps.search import MapsSearchClient
135+
136+
# Use Azure Maps subscription key authentication
137+
subscription_key = os.getenv("SUBSCRIPTION_KEY")
138+
maps_search_client = MapsSearchClient(
139+
credential=AzureKeyCredential(subscription_key)
140+
)
141+
```
142+
143+
## Fuzzy Search an Entity
144+
145+
The following code snippet demonstrates how, in a simple console application, to import the `Azure.Maps.Search` package and perform a fuzzy search on “Starbucks” near Seattle. This example uses subscription key credentials to authenticate MapsSearchClient. In `demo.py`:
146+
147+
```Python
148+
import os
149+
from azure.core.credentials import AzureKeyCredential
150+
from azure.maps.search import MapsSearchClient
151+
152+
def fuzzy_search():
153+
    # Use Azure Maps subscription key authentication
154+
subscription_key = os.getenv("SUBSCRIPTION_KEY")
155+
    maps_search_client = MapsSearchClient(
156+
        credential=AzureKeyCredential(subscription_key)
157+
    )
158+
    result = maps_search_client.fuzzy_search(
159+
        query="Starbucks",
160+
        coordinates=(47.61010, -122.34255)
161+
    )
162+
    # Print the search results
163+
    print("Starbucks search result nearby Seattle:")
164+
    for result_item in result.results:
165+
        print(f"* {result_item.address.street_number } {result_item.address.street_name }")
166+
        print(f" {result_item.address.municipality } {result_item.address.country_code } {result_item.address.postal_code }")
167+
        print(f" Coordinate: {result_item.position.lat}, {result_item.position.lon}"
168+
)
169+
170+
if __name__ == '__main__':
171+
    fuzzy_search()
172+
```
173+
174+
The sample code above instantiates `AzureKeyCredential` with the Azure Maps subscription key, then it to instantiate the `MapsSearchClient` object. The methods provided by `MapsSearchClient` forward the request to the Azure Maps REST endpoints. In the end, the program iterates through the results and prints the address and coordinates for each result.
175+
176+
After finishing the program, run `python demo.py` from the project folder in PowerShell:
177+
178+
```powershell
179+
python demo.py
180+
```
181+
182+
You should see a list of Starbucks address and coordinate results:
183+
184+
```text
185+
* 1912 Pike Place
186+
Seattle US 98101
187+
Coordinate: 47.61016, -122.34248
188+
* 2118 Westlake Avenue
189+
Seattle US 98121
190+
Coordinate: 47.61731, -122.33782
191+
* 2601 Elliott Avenue
192+
Seattle US 98121
193+
Coordinate: 47.61426, -122.35261
194+
* 1730 Howell Street
195+
Seattle US 98101
196+
Coordinate: 47.61716, -122.3298
197+
* 220 1st Avenue South
198+
Seattle US 98104
199+
Coordinate: 47.60027, -122.3338
200+
* 400 Occidental Avenue South
201+
Seattle US 98104
202+
Coordinate: 47.5991, -122.33278
203+
* 1600 East Olive Way
204+
Seattle US 98102
205+
Coordinate: 47.61948, -122.32505
206+
* 500 Mercer Street
207+
Seattle US 98109
208+
Coordinate: 47.62501, -122.34687
209+
* 505 5Th Ave S
210+
Seattle US 98104
211+
Coordinate: 47.59768, -122.32849
212+
* 425 Queen Anne Avenue North
213+
Seattle US 98109
214+
Coordinate: 47.62301, -122.3571
215+
```
216+
217+
## Search an Address
218+
219+
Call the `SearchAddress` method to get the coordinate of an address. Modify the Main program from the sample as follows:
220+
221+
```Python
222+
import os
223+
from azure.core.credentials import AzureKeyCredential
224+
from azure.maps.search import MapsSearchClient
225+
226+
def search_address():
227+
subscription_key = os.getenv("SUBSCRIPTION_KEY")
228+
229+
    maps_search_client = MapsSearchClient(
230+
credential=AzureKeyCredential(subscription_key)
231+
)
232+
233+
  result = maps_search_client.search_address(
234+
query="1301 Alaskan Way, Seattle, WA 98101, US"
235+
)
236+
    print(f"Coordinate: {result.results[0].position.lat}, {result.results[0].position.lon}")
237+
238+
if __name__ == '__main__':
239+
    search_address()
240+
```
241+
242+
Results returned by the `search_address()` method are ordered by confidence score and print the coordinates of the first result.
243+
244+
## Batch reverse search
245+
246+
Azure Maps Search also provides some batch query methods. These methods will return long-running operations (LRO) objects. The requests might not return all the results immediately, so users can choose to wait until completion or query the result periodically. The examples below demonstrate how to call the batched reverse search method.
247+
248+
Since these return LRO objects, you'll need the `asyncio` method included in the `aiohttp` package:
249+
250+
```powershell
251+
pip install aiohttp
252+
```
253+
254+
```Python
255+
import asyncio
256+
import os
257+
from azure.core.credentials import AzureKeyCredential
258+
from azure.maps.search.aio import MapsSearchClient
259+
260+
async def begin_reverse_search_address_batch():
261+
subscription_key = os.getenv("SUBSCRIPTION_KEY")
262+
263+
    maps_search_client = MapsSearchClient(AzureKeyCredential(subscription_key))
264+
265+
    async with maps_search_client:
266+
        result = await maps_search_client.begin_reverse_search_address_batch(
267+
            search_queries = [
268+
                "148.858561,2.294911",
269+
                "47.639765,-122.127896&radius=5000",
270+
                "47.61559,-122.33817&radius=5000",
271+
            ]
272+
        )
273+
    print(f"Batch_id: {result.batch_id}")
274+
275+
if __name__ == '__main__':
276+
# Special handle for Windows platform
277+
if os.name == 'nt':
278+
    asyncio.set_event_loop_policy(asyncio.WindowsSelectorEventLoopPolicy())
279+
    asyncio.run(begin_reverse_search_address_batch())
280+
```
281+
282+
In the above example, three queries are passed to the batched reverse search request. To get the LRO results, the request will create a batch request with a batch ID as result that can be used to fetch batch response later. The LRO results will be cached on the server side for 14 days.
283+
284+
The following example demonstrates the process of calling the batch ID and retrieving the operation results of the batch request:
285+
286+
```python
287+
import asyncio
288+
import os
289+
from azure.core.credentials import AzureKeyCredential
290+
from azure.maps.search.aio import MapsSearchClient
291+
292+
async def begin_reverse_search_address_batch():
293+
subscription_key = os.getenv("SUBSCRIPTION_KEY")
294+
295+
    maps_search_client = MapsSearchClient(credential=AzureKeyCredential(subscription_key))
296+
297+
    async with maps_search_client:
298+
        result = await maps_search_client.begin_reverse_search_address_batch(
299+
            search_queries = [
300+
                "148.858561,2.294911",
301+
                "47.639765,-122.127896&radius=5000",
302+
                "47.61559,-122.33817&radius=5000",
303+
            ]
304+
        )
305+
    return result
306+
307+
async def begin_reverse_search_address_batch_with_id(batch_id):
308+
    subscription_key = os.getenv("SUBSCRIPTION_KEY")
309+
    maps_search_client = MapsSearchClient(credential=AzureKeyCredential(subscription_key))
310+
    async with maps_search_client:
311+
        result = await maps_search_client.begin_reverse_search_address_batch(
312+
            batch_id=batch_id,
313+
        )
314+
315+
    responses = result._polling_method._initial_response.context.get('deserialized_data')
316+
    summary = responses['summary']
317+
318+
# Print Batch results
319+
    idx = 1
320+
print(f"Total Batch Requests: {summary['totalRequests']}, Total Successful Results: {summary['successfulRequests']}")
321+
for items in responses.get('batchItems'):
322+
if items['statusCode'] == 200:
323+
print(f"Request {idx} result:")
324+
for address in items['response']['addresses']:
325+
print(f" {address['address']['freeformAddress']}")
326+
else:
327+
print(f"Error in request {idx}: {items['response']['error']['message']}")
328+
idx += 1
329+
330+
async def main():
331+
    result = await begin_reverse_search_address_batch()
332+
    await begin_reverse_search_address_batch_with_id(result.batch_id)
333+
334+
if __name__ == '__main__':
335+
# Special handle for Windows platform
336+
if os.name == 'nt':
337+
asyncio.set_event_loop_policy(asyncio.WindowsSelectorEventLoopPolicy())
338+
    asyncio.run(main())
339+
```
340+
341+
## Additional information
342+
343+
The [Azure Maps Search Package client library for Python][Search package client library] in the *Azure SDK for Python Preview* documentation.
344+
345+
<!--------------------------------------------------------------------------------------------------------------->
346+
[Azure Maps account]: quick-demo-map-app.md#create-an-azure-maps-account
347+
[Subscription key]: quick-demo-map-app.md#get-the-primary-key-for-your-account
348+
[authentication]: azure-maps-authentication.md
349+
350+
[Search package client library]: /python/api/overview/azure/maps-search-readme?view=azure-python-preview
351+
[python latest release]: https://www.python.org/downloads/
352+
353+
<!-- Python SDK Developers Guide --->
354+
[support policy]: https://github.com/Azure/azure-sdk-for-python/wiki/Azure-SDKs-Python-version-support-policy
355+
[py search package]: https://pypi.org/project/azure-maps-search
356+
[py search readme]: https://github.com/Azure/azure-sdk-for-python/blob/main/sdk/maps/azure-maps-search/README.md
357+
[py search sample]: https://github.com/Azure/azure-sdk-for-python/tree/main/sdk/maps/azure-maps-search/samples
358+
[py route package]: https://pypi.org/project/azure-maps-route
359+
[py route readme]: https://github.com/Azure/azure-sdk-for-python/blob/main/sdk/maps/azure-maps-route/README.md
360+
[py route sample]: https://github.com/Azure/azure-sdk-for-python/tree/main/sdk/maps/azure-maps-route/samples
361+
[py render package]: https://pypi.org/project/azure-maps-render
362+
[py render readme]: https://github.com/Azure/azure-sdk-for-python/blob/main/sdk/maps/azure-maps-render/README.md
363+
[py render sample]: https://github.com/Azure/azure-sdk-for-python/tree/main/sdk/maps/azure-maps-render/samples
364+
[py geolocation package]: https://pypi.org/project/azure-maps-geolocation
365+
[py geolocation readme]: https://github.com/Azure/azure-sdk-for-python/blob/main/sdk/maps/azure-maps-geolocation/README.md
366+
[py geolocation sample]: https://github.com/Azure/azure-sdk-for-python/tree/main/sdk/maps/azure-maps-geolocation/samples
367+
368+
<!--- Authentication ---->
369+
[Azure Identity package]: https://github.com/Azure/azure-sdk-for-python/tree/main/sdk/identity/azure-identity
370+
[defaultazurecredential]: https://github.com/Azure/azure-sdk-for-python/tree/main/sdk/identity/azure-identity#defaultazurecredential
371+
[Host daemon]: ./how-to-secure-daemon-app.md#host-a-daemon-on-non-azure-resources
372+
[View authentication details]: how-to-manage-authentication.md#view-authentication-details

articles/azure-maps/rest-sdk-developer-guide.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ Azure Maps Python SDK supports Python version 3.7 or later. Check the [Azure S
4040
| [Render][py render readme]| [azure-maps-render][py render package]|[render sample][py render sample] |
4141
| [Geolocation][py geolocation readme]|[azure-maps-geolocation][py geolocation package]|[geolocation sample][py geolocation sample] |
4242

43-
<!--For more information, see the [python SDK Developers Guide](how-to-dev-guide-py-sdk.md).-->
43+
For more information, see the [python SDK Developers Guide](how-to-dev-guide-py-sdk.md).
4444

4545
## JavaScript/TypeScript
4646

0 commit comments

Comments
 (0)