How to set up a Python environment on Azure App Service (Windows)
Applies to: Visual Studio Visual Studio for Mac
Note
This article applies to Visual Studio 2017. If you're looking for the latest Visual Studio documentation, see Visual Studio documentation. We recommend upgrading to the latest version of Visual Studio. Download it here
Azure App Service is a platform-as-a-service offering for web apps, whether they are sites accessed through a browser, REST APIs used by your own clients, or event-triggered processing. App Service fully supports using Python to implement apps.
Customizable Python support for Azure App Service is provided as a set of App Service site extensions that each contain a specific version of the Python runtime. You can then install any desired packages directly into that environment, as described in this article. By customizing the environment in the App Service itself, you don't need to maintain packages in your web app projects or upload them with the app code.
Tip
Although App Service by default has Python 2.7 and Python 3.4 installed in root folders on the server, you cannot customize or install packages in these environments, nor should you depend on their presence. You should instead rely on a site extension that you control, as described in this article.
Choose a Python version through the Azure portal
Create an App Service for your web app on the Azure portal.
On the App Service's page, scroll to the Development Tools section, select Extensions, then select + Add.
Scroll down in the list to the extension that contains the version of Python you want:
Tip
If you need an older version of Python and don't see it listed in the site extensions, you can still install it through the Azure Resource Manager as described in the next section.
Select the extension, accept the legal terms, then select OK.
A notification appears in the portal when installation is complete.
Choose a Python version through the Azure Resource Manager
If you are deploying an App Service with an Azure Resource Manager template, add the site extension as a resource. Specifically, the extension appears as a nested resource (a resources
object under resources
) with the type siteextensions
.
For example, after adding a reference to python361x64
(Python 3.6.1 x64), your template may look like the following (some properties omitted):
"resources": [
{
"apiVersion": "2015-08-01",
"name": "[parameters('siteName')]",
"type": "Microsoft.Web/sites",
// ...
"resources": [
{
"apiVersion": "2015-08-01",
"name": "python361x64",
"type": "siteextensions",
"properties": { },
"dependsOn": [
"[resourceId('Microsoft.Web/sites', parameters('siteName'))]"
]
},
// ...
]
}
Set web.config to point to the Python interpreter
After installing the site extension (through either the portal or an Azure Resource Manager template), you next point your app's web.config file to the Python interpreter. The web.config file instructs the IIS (7+) web server running on App Service about how it should handle Python requests through either HttpPlatform (recommended) or FastCGI.
Begin by finding the full path to the site extension's python.exe, then create and modify the appropriate web.config file.
Find the path to python.exe
A Python site extension is installed on the server under d:\home in a folder appropriate to the Python version and architecture (except in the case of a few older versions). For example, Python 3.6.1 x64 is installed in d:\home\python361x64. The full path to the Python interpreter is then d:\home\python361x64\python.exe.
To see the specific path on your App Service, select Extensions on the App Service page, then select the extension in the list.
This action opens the extension's description page containing the path:
If you have trouble seeing the path for the extension, you can find it manually using the console:
- On your App Service page, select the Development Tools > Console.
- Enter the command
ls ../home
ordir ..\home
to see the top-level extensions folders, such as Python361x64. - Enter a command like
ls ../home/python361x64
ordir ..\home\python361x64
to verify that it contains python.exe and other interpreter files.
Configure the HttpPlatform handler
The HttpPlatform module passes socket connections directly to a standalone Python process. This pass-through allows you to run any web server you like, but requires a startup script that runs a local web server. You specify the script in the <httpPlatform>
element of web.config, where the processPath
attribute points to the site extension's Python interpreter and the arguments
attribute points to your script and any arguments you want to provide:
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<system.webServer>
<handlers>
<add name="PythonHandler" path="*" verb="*" modules="httpPlatformHandler" resourceType="Unspecified"/>
</handlers>
<httpPlatform processPath="D:\home\Python361x64\python.exe"
arguments="D:\home\site\wwwroot\runserver.py --port %HTTP_PLATFORM_PORT%"
stdoutLogEnabled="true"
stdoutLogFile="D:\home\LogFiles\python.log"
startupTimeLimit="60"
processesPerApplication="16">
<environmentVariables>
<environmentVariable name="SERVER_PORT" value="%HTTP_PLATFORM_PORT%" />
</environmentVariables>
</httpPlatform>
</system.webServer>
</configuration>
The HTTP_PLATFORM_PORT
environment variable shown here contains the port that your local server should listen on for connections from localhost. This example also shows how to create another environment variable, if desired, in this case SERVER_PORT
.
Configure the FastCGI handler
FastCGI is an interface that works at the request level. IIS receives incoming connections and forwards each request to a WSGI app running in one or more persistent Python processes. The wfastcgi package is pre-installed and configured with each Python site extension, so you can easily enable it by including the code in web.config like what's shown below for a web app based on the Bottle framework. Note that the full paths to python.exe and wfastcgi.py are placed in the PythonHandler
key:
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<appSettings>
<add key="PYTHONPATH" value="D:\home\site\wwwroot"/>
<!-- The handler here is specific to Bottle; other frameworks vary. -->
<add key="WSGI_HANDLER" value="app.wsgi_app()"/>
<add key="WSGI_LOG" value="D:\home\LogFiles\wfastcgi.log"/>
</appSettings>
<system.webServer>
<handlers>
<add name="PythonHandler" path="*" verb="*" modules="FastCgiModule"
scriptProcessor="D:\home\Python361x64\python.exe|D:\home\Python361x64\wfastcgi.py"
resourceType="Unspecified" requireAccess="Script"/>
</handlers>
</system.webServer>
</configuration>
The <appSettings>
defined here are available to your app as environment variables:
- The value for
PYTHONPATH
may be freely extended but must include the root of your app. WSGI_HANDLER
must point to a WSGI app importable from your app.WSGI_LOG
is optional but recommended for debugging your app.
See Publish to Azure for additional details on web.config contents for Bottle, Flask, and Django web apps.
Install packages
The Python interpreter installed through a site extension is only one piece of your Python environment. You likely need to install different packages in that environment as well.
To install packages directly in the server environment, use one of the following methods:
Methods | Usage |
---|---|
Azure App Service Kudu console | Installs packages interactively. Packages must be pure Python or must publish wheels. |
Kudu REST API | Can be used to automate package installation. Packages must be pure Python or must publish wheels. |
Bundle with app | Install packages directly into your project and then deploy them to App Service as if they were part of your app. Depending on how many dependencies you have and how frequently you update them, this method may be the easiest way to get a working deployment going. Be advised that libraries must match the version of Python on the server, otherwise you see obscure errors after deployment. That said, because the versions of Python in the App Service site extensions are exactly the same as those versions released on python.org, you can easily obtain a compatible version for local development. |
Virtual environments | Not supported. Instead, use bundling and set the PYTHONPATH environment variable to point to the location of the packages. |
Azure App Service Kudu console
The Kudu console gives you direct, elevated command-line access to the App Service server and its file system. This is both a valuable debugging tool and allows for CLI operations such as installing packages.
Open Kudu from your App Service page on the Azure portal by selecting Development Tools > Advanced Tools, then selecting Go. This action navigates to a URL that's the same as your base App Service URL except with
.scm
inserted. For example, if your base URL ishttps://vspython-test.azurewebsites.net/
then Kudu is onhttps://vspython-test.scm.azurewebsites.net/
(which you can bookmark):Select Debug console > CMD to open the console, in which you can navigate into your Python installation and see what libraries are already there.
To install a single package:
a. Navigate to the folder of the Python installation where you want to install the package, such as d:\home\python361x64.
b. Use
python.exe -m pip install <package_name>
to install a package.If you've deployed a requirements.txt for your app to the server already, install all those requirements as follows:
a. Navigate to the folder of the Python installation where you want to install the package, such as d:\home\python361x64.
b. Run the command
python.exe -m pip install --upgrade -r d:\home\site\wwwroot\requirements.txt
.Using requirements.txt is recommended because it's easy to reproduce your exact package set both locally and on the server. Just remember to visit the console after deploying any changes to requirements.txt and run the command again.
Note
There's no C compiler on App Service, so you need to install the wheel for any packages with native extension modules. Many popular packages provide their own wheels. For packages that don't, use pip wheel <package_name>
on your local development computer and then upload the wheel to your site. For an example, see Manage required packages with requirements.txt.
Kudu REST API
Instead of using the Kudu console through the Azure portal, you can run commands remotely through the Kudu REST API by posting the command to https://yoursite.scm.azurewebsites.net/api/command
. For example, to install the bottle
package, post the following JSON to /api/command
:
{
"command": 'python.exe -m pip install bottle',
"dir": '\home\python361x64'
}
For information about commands and authentication, see the Kudu documentation.
You can also see credentials using the az webapp deployment list-publishing-profiles
command through the Azure CLI (see az webapp deployment). A helper library for posting Kudu commands is available on GitHub.