Update: Others, like Jeff Hollan, have been able to get am Azure Function working with Python. He did have to change something in the requirements.txt as well, same as I mentioned here. Have a look at this GitHub issue. I’ll give it another shot myself soon. Update: Read about my second attempt here
Googling led me to a couple of blog posts about Python on Azure Functions. Those led me to believe Python on Azure Functions is using Windows as OS, uses a very old Python version and is very slow.
Even Microsoft’s own Azure Functions Supported Languages is stating Python isn’t supported on runtime 2.x.
Finally, I went to the Azure Functions Python Worker GitHub page and read something a little more inspiring: Python 3.6, Linux and the 2.x runtime :-) I decided to give it a try on my Windows 10 machine with Visual Studio Code. Here is what I did and what my experience and result was like.
Azure Functions in Python support in Visual Studio Code is still very basic. Building, testing, debugging and publishing is still done with the CLI. Support for a truely serverless deployment via the Consumption Plan isn’t there as well yet, for now you’re stuck with an App Service Plan. Last, not all bindings that are available for C# are available for Python yet, so no cool Service Bus integration at this moment. All these issues are being worked on though!
What you would find if you would read this to the end, is that I ended up with a terrible exception when running from Azure. Everything works on my machine, but this definately isn’t production ready yet. Hence the preview status I guess ;)
The requirements in the tutorial state Python 3.6.4 or above. So, I installed the latest Python 3.7. Bad idea, as the scripts only work with 3.6. So I installed 3.6 next to 3.7 and unchecked the “Add to Path” option to make sure there are no conflicts. If you don’t want to do anything else with Python, just install 3.6 only. You can find all installers at the Python website
Create a 3.6 virtual environment inside your soon to-be project directory, by issuing this command to the Python launcher py: py -3.6 -m venv C:\Projects\MyFunctionApp\env.
FYI: You can use py -0 to check which Python versions are available, if you have multiple installed.
Next you have to activate the virtual environment. Do this by executing C:\Projects\MyFunctionApp\env\Scripts\activate.bat. This results in a new prompt.
FYI: To exit the activated virtual environment, just type in the command deactivate
From within the virtual environment, issue the command func init C:\Projects\MyFunctionApp --worker-runtime python to initialize an empty Azure Functions App in the already existing “C:\Projects\MyFunctionApp” directory.
By initializing the virtual environment inside of the project directory, VSCode will automatically detect this virtual environment. Be sure to add the “env” directory to your .gitignore file! This appears to be a best practice.
You should now have the following structure:
C:\Projects\MyFunctionApp, containing your Azure Function App.
C:\Projects\MyFunctionApp\env, containing a Python 3.6 virtual environment, which is just a clean Python environment, exclusively for this project.
Start Visual Studio code and open the folder “C:\Projects\MyFunctionApp” and click ‘Yes’ when asked if you want to initialize the project for optimal use with VS Code. Pick ‘Python’ in the next step.
Congratulations, you now have a working, empty, Python Azure Function App! :-)
Adding a function to your app:
Make sure your virtual environment is being used:
By clicking on the “Python 3.6.6 (venv)” button, bottom-left in the blue status bar, and choosing the one that points to your virtual environment if it isn’t already.
You can also use the Control-Shift-P shortcut and type: Python: Select Interpreter, which results in the same dropdown.
Open a Python terminal in VSCode by pressing Control-Shift-P and then type: Python: Create Terminal. This should supply you with a shell within your project directory and automatically activate your Python virtual environment.
You can doublecheck if you’re in your virtual environment by looking at the prompt, it should start with (env), or whatever your virtual environment is called.
FIY: If you have multiple Python versions installed, when you issue the command python --version from your virtual environment, it will still say 3.7.0 or whatever is on your system path. The virtual environment does have its own python executable in “Scripts\python.exe”, so if you issue the command env\Scripts\python --version it will say 3.6.6. Not sure if or when this will be an issue. Tools such as pip (see the section about fixing missing modules) are smart enough to notice they’re being run inside a virtual environment and automatically adjust.
Adding a function is straightforward, type: func new. You can then choose which kind of trigger. These are supported at this moment:
When opening the “__init__.py” file from your new function, VSCode will probably complain about no linter being installed. Install it when asked for.
When you re-open the “ __init__.py” file, you should get the error “Unable to import ‘azure.functions’”. This is correct, as that module isn’t available yet.
Fixing your missing modules - update:
You probably want to adjust the requirements.txt and get rid of the whole “-e git+https://github….” line and replace it with “azure-functions”. That just downloads the latest azure-functions module, without any GIT clone, manual compiling or necessity for Visual C++ 14.0. It’s a whole lot faster too. No idea why this isn’t the default configuration when creating a new Function App with the Azure Function Core Tools.
Run pip install -r .\requirements.txt from the Python terminal and you’re good to go.
Fixing your missing modules - the original:
All dependencies are listed in the requirements.txt file. You can install them by issuing this command in your Python terminal: pip install -r .\requirements.txt.
If you’re serious about your Python development you should have a look at pipenv, which addresses some issues with pip and virtual environments.
Installing the dependencies will probably fail with the message: “Microsoft Visual C++ 14.0 is required” and sent you to an URL which doesn’t exist. Nice ;) Install Visual Studio Build Tools 2017 to fix this. Have a look at Windows Compilers for more information.
I probably did something wrong the first time installing, as I still got the same error after installing. Started up “Visual Studio Installer” again to modify my “Visual Studio Build Tools 2017” installation and noticed the workload “Visual C++ build tools” wasn’t checked at all. So be sure to mark that checkbox!
Do not uncheck any of the individual components installed by that workload, like the Windows 10 SDK. That results the following error message when installing the dependencies: “fatal error C1083: Cannot open include file: ‘io.h’: No such file or directory”.
Rerun pip install -r .\requirements.txt and have quite some patience as it is cloning the Azure Functions Python Worker repository and builds it, I think ;)
A “src” directory stays behind after installation, as far as I know you can safely delete this.
FIW: You can run pip list to see which modules are installed.
Now probably everything up until here was sort of smooth, so brace yourself for the next part ;)
Publishing to Azure
Type in pip freeze > requirements.txt in your Python terminal. This generates a new requirements.txt with any new dependencies. This is used in the Docker build when publishing.
Use this magic URL to enable Python when creating a new App Function. Have a look at the querystring! Btw, you must pick Linux to be able to choose Python.
When I navigated to my new Function App the result was a HTTP 502 error for quite some time. After a while the regular “Your Function App 2.0 preview is up and running” website came up. Something was very slow.
Now just follow the steps from the tutorial:
Log into your Azure account: func azure login
Set your subscription if you have more than one: func azure subscriptions list & func azure account set <subscription id>
Publish to the function app created in step 2: func azure functionapp publish <app name>
Publishing will again take quite some time. This is a known issue and apparently is being worked on. If you’re still building the azure-functions-python-worker code, it doesn’t seem to end at all and gets stuck on uploading artifact.
Trying it out!
After fetching the URL for my HTTP trigger from the Azure Portal, I opened my favorite browser and hit the endpoint. HTTP ERROR 500.
Opened up AppInsights, which gave me a totally worthless stacktrace (see below), after which I gave up. I might submit a ticket later and post a new blog with the solution if I manage to fix this.
What next if you do manage to get something working
Well, the next thing on your list should probably be building a proper CI/CD pipeline for this. And bonus, you’ll probably spend less time waiting too. You’re on your own for that, but you can always reach out to me if you need any help!
The exception (nothing below this, don’t bother scrolling ;))