The Azure Functions extension for VS Code greatly simplifies the process of using Functions by automatically handling many configuration concerns.
If you encounter any problems in the course of this tutorial, feel free to file an issue in the Visual Studio Code documentation repository.
Details for each of these are in the sections that follow:
If you don’t have an Azure subscription, sign up now for a free 30-day account with $200 in Azure credits to try out any combination of services.
Install the following software:
Follow the instructions for your operating system on Work with Azure Functions Core Tools in the Azure documentation. (The tools themselves are written in .NET Core, and the Core Tools package is best installed using the Node.js package manager, npm, which is why you need to install .NET Core and Node.js at present, even for Python code. Fortunately, you need install these components only once, after which VS Code automatically prompts you to install any updates.)
Once the Functions extension is installed, sign into your Azure account by navigating to the Azure: Functions explorer, select Sign in to Azure, and follow the prompts.
After signing in, verify that you see the email account of your Azure subscription in the Status Bar:
The name you’ve assigned to your subscription also appears in the Azure: Functions explorer (“Primary” in the image below):
Note: If you see the error “Cannot find subscription with name [subscription ID]”, this may be because you are behind a proxy and unable to reach the Azure API. Configure
HTTP_PROXY
andHTTPS_PROXY
environment variables with your proxy information in your terminal:
# macOS/Linux
export HTTPS_PROXY=https://username:password@proxy:8080
export HTTP_PROXY=http://username:password@proxy:8080
#Windows
set HTTPS_PROXY=https://username:password@proxy:8080
set HTTP_PROXY=http://username:password@proxy:8080
To verify that all the Azure Functions tools are installed, select the Terminal: Create New Integrated Terminal command from the Command Palette (Ctrl+Shift+P), then run the command func
:
The output that starts with the Azure Functions logo (you need to scroll the output upwards) indicates that the Azure Functions Core Tools are present.
__init__.py
file that contains the default function code:Note If VS Code tells you that you don’t have a Python interpreter selected when it opens
__init__.py
, use the Python: Select Interpreter command from the Command Palette and select the virtual environment in the local.env
folder (which was created as part of the project).
Tip: Whenever you want to create another function in the same project, use the Create Function command in the Azure: Functions explorer, or use the Azure Functions: Create Function command from the Command Palette (Ctrl+Shift+P). Both commands prompt you for a function name (which is the name of the endpoint), then creates a subfolder with the default files.
In the newly created function subfolder, you see three files: __init__.py
contains the function’s code, function.json
describes the function to Azure Functions, and sample.dat
is a sample data file. You can delete sample.dat
if you want, as it exists only to show that you can add other files to the subfolder.
Let’s look at function.json
first, then the code in __init__.py
.
The function.json file provides the necessary configuration information for the Azure Functions endpoint:
{
"scriptFile": "\_\_init\_\_.py",
"bindings": \[
{
"authLevel": "anonymous",
"type": "httpTrigger",
"direction": "in",
"name": "req",
"methods": \[
"get",
"post"
\]
},
{
"type": "http",
"direction": "out",
"name": "$return"
}
\]
}
You can see that scriptFile
identifies the startup file for the code, which must contain a Python function named main
. You can factor your code into multiple files so long as the file specified here contains a main
function.
The bindings
element contains two objects, one to describe incoming requests, and the other to describe the HTTP response. For incoming requests ("direction": "in"
), the function responds to HTTP GET or POST requests and doesn’t require authentication. The response ("direction": "out"
) is an HTTP response that returns whatever value is returned from the main
Python function.
When you create a new function, Azure Functions provides default Python code in __init__.py
:
import logging
import azure.functions as func
def main(req: func.HttpRequest) -> func.HttpResponse:
logging.info(‘Python HTTP trigger function processed a request.’)
name = req.params.get('name')
if not name:
try:
req\_body = req.get\_json()
except ValueError:
pass
else:
name = req\_body.get('name')
if name:
return func.HttpResponse(f"Hello {name}!")
else:
return func.HttpResponse(
"Please pass a name on the query string or in the request body",
status\_code=400
)
The important parts of the code are as follows:
func
from azure.functions
; importing the logging module is optional but recommended.main
Python function receives a func.request
object named req
, and returns a value of type func.HttpResponse
. You can learn more about the capabilities of these objects in the func.HttpRequest and func.HttpResponse references.main
then processes the request and generates a response. In this case, the code looks for a name
parameter in the URL. Failing that, it checks if the request body contains JSON (using func.HttpRequest.get_json
) and that the JSON contains a name
value (using the get
method of the JSON object returned by get_json
)..vscode/launch.json
that contains a single configuration named Attach to Python Functions. This configuration means you can just press F5 or use the Debug explorer to start the project:Hosting environment: Production
Content root path: d:\Examples\Python\AzureFunctions
Now listening on: http://0.0.0.0:7071
Application started. Press Ctrl+C to shut down.
Http Functions:
HttpExample: \[GET,POST\] http://localhost:7071/api/HttpExample
api/<function_name>
, in this case api/HttpExample
. However, because that URL doesn’t include a name parameter, the browser window should just show, “Please pass a name on the query string or in the request body” as appropriate for that path in the code.[http://localhost:7071/api/HttpExample?name=VS%20Code](http://localhost:7071/api/HttpExample?name=VS%20Code)
, and in the browser window you should see the message, “Hello VS Code!”, demonstrating that you’ve run that code path.# Mac OS/Linux: modify the URL if you’re using a different function name
curl --header “Content-Type: application/json” --request POST \
–data {“name”:“VS Code”} http://localhost:7071/api/HttpExample
curl --header “Content-Type: application/json” --request POST \
–data {“”“name”“”:“”“VS Code”“”} http://localhost:7071/api/HttpExample
data.json
that contains {"name":"VS Code"}
and use the command curl --header "Content-Type: application/json" --request POST --data @data.json [http://localhost:7071/api/HttpExample](http://localhost:7071/api/HttpExample)
.name = req.params.get('name')
and make a request to the URL again. The VS Code debugger should stop on that line, allowing you to examine variables and step through the code. (For a short walkthrough of basic debugging, see Tutorial - Configure and run the debugger.)In these steps, you use the Functions extension to create a “Function App” on Azure. A Function App is composed of a storage account for data, an App Service Plan (which corresponds to the Linux virtual machine on which the App Service runs), and an App Service (the hosting service for your endpoints that runs on the virtual machine). All of these resources are organized within a single resource group.
HTTP Trigger Urls:
HttpExample: https://vscode-azure-functions.azurewebsites.net/api/HttpExample
After your first deployment, you can make changes to your code, such as adding additional functions, and redeploy to the same Functions App.
__init__.py
, function.json
, and sample.dat
.__init__.py
to match the following, which generates a string containing the value of PI to a number of digits specified in the URL (this code uses only a URL parameter)import logging
import azure.functions as func
“”" Adapted from the second, shorter solution at http://www.codecodex.com/wiki/Calculate_digits_of_pi#Python
“”"
def pi_digits_Python(digits):
scale = 10000
maxarr = int((digits / 4) * 14)
arrinit = 2000
carry = 0
arr = [arrinit] * (maxarr + 1)
output = “”
for i in range(maxarr, 1, -14):
total = 0
for j in range(i, 0, -1):
total = (total \* j) + (scale \* arr\[j\])
arr\[j\] = total % ((j \* 2) - 1)
total = total / ((j \* 2) - 1)
output += "%04d" % (carry + (total / scale))
carry = total % scale
return output;
def main(req: func.HttpRequest) -> func.HttpResponse:
logging.info(‘DigitsOfPi HTTP trigger function processed a request.’)
digits\_param = req.params.get('digits')
if digits\_param is not None:
try:
digits = int(digits\_param)
except ValueError:
digits = 10 # A default
if digits > 0:
digit\_string = pi\_digits\_Python(digits)
# Insert a decimal point in the return value
return func.HttpResponse(digit\_string\[:1\] + '.' + digit\_string\[1:\])
return func.HttpResponse(
"Please pass the URL parameter ?digits= to specify a positive number of digits.",
status\_code=400
)
function.json
so that the "methods"
collection contains only "get"
(that is, remove "post"
). The whole file should appear as follows:{
“scriptFile”: “__init__.py”,
“bindings”: [
{
“authLevel”: “anonymous”,
“type”: “httpTrigger”,
“direction”: “in”,
“name”: “req”,
“methods”: [
“get”
]
},
{
“type”: “http”,
“direction”: “out”,
“name”: “$return”
}
]
}
Http Functions:
DigitsOfPi: \[GET\] http://localhost:7071/api/DigitsOfPi
HttpExample: \[GET,POST\] http://localhost:7071/api/HttpExample
[http://localhost:7071/api/DigitsOfPi?digits=125](http://localhost:7071/api/DigitsOfPi?digits=125)
and observe the output. (You might notice that the code algorithm isn’t entirely accurate, but we’ll leave the improvements to you!) Stop the debugger when you’re finished.The Function App you created includes resources that can incur minimal costs (refer to Functions Pricing). To clean up the resources, right-click the Function App in the Azure: Functions explorer and select Delete Function App. You can also visit the Azure portal, select Resource groups from the left-side navigation pane, select the resource group that was created in the process of this tutorial, and then use the Delete resource group command.
Congratulations on completing this walkthrough of deploying Python code to Azure Functions! You’re now ready to create many more serverless functions.
As noted earlier, you can learn more about the Functions extension by visiting its GitHub repository, vscode-azurefunctions. Issues and contributions are also welcome.
To learn more about Azure Functions, browse the Azure Functions documentation, and especially explore the different triggers you can use.
To learn more about Azure services that you can use from Python, including data storage along with AI and Machine Learning services, visit Azure Python Developer Center.
There are also other Azure extensions for VS Code that you may find helpful. Just search on “Azure” in the Extensions explorer:
Some popular extensions are:
And again, if you encountered any problems in the course of this tutorial, feel free to file an issue in the VS Code docs repo.
#python #azure