重要
从 2024 年 9 月 1 日开始,云服务(经典版)对所有客户已停止支持。 从 2024 年 10 月开始,Microsoft 将停止并关闭任何正在运行的现有部署,数据将永久性丢失。 新部署应使用基于 Azure 资源管理器的新型部署模型 Azure 云服务(外延支持)。
本文概述了如何使用 Python Tools for Visual Studio 配置和操作 Python Web 角色和工作者角色。 介绍如何使用 Visual Studio 来创建和部署使用 Python 的基本云服务。
先决条件
- Visual Studio 2013、2015 或 2017
- Python Tools for Visual Studio (用于 Visual Studio 的 Python 工具,简称 PTVS)
-
适用于 Visual Studio (VS) 2013 的 Azure SDK 工具 或
用于 VS 2015 的 Azure SDK 工具或
用于 VS 2017 的 Azure SDK 工具 - Python 2.7 32 位或 Python 3.8 32 位
注释
若要完成本教程,需要一个 Azure 帐户。 可以激活 Visual Studio 订户权益或注册免费试用帐户。
什么是 Python Web 角色和工作角色?
Azure 提供了三种用于运行应用程序的计算模型:Azure 应用服务中的 Web 应用功能、Azure 虚拟机和 Azure 云服务。 这三种模型都支持 Python。 云服务(包括 Web 角色和工作角色)提供了平台即服务 (PaaS)。 在云服务中,Web 角色提供专门用于托管前端 Web 应用程序的 Internet Information Services (IIS) Web 服务器。 工作角色可以运行异步的、长时间运行的或永久性的任务,这些任务独立于用户交互或输入。
有关详细信息,请参阅 什么是云服务?。
注释
想要构建一个简单的网站?
如果方案只涉及一个简单的网站前端,请考虑使用 Azure 应用服务中的轻型 Web 应用功能。 随着网站的不断扩大和需求的不断变化,用户可将其轻松升级到云服务。 请参阅 Python 开发人员中心关于如何在 Azure 应用服务中开发 Web 应用功能的文章。
创建项目
在 Visual Studio 中,可以在“新建项目”对话框的“Python”下选择“Azure 云服务”。
在 Azure 云服务向导中,可以创建新的 Web 角色和 Worker 角色。
工作角色模板附带用于连接 Azure 存储帐户或 Azure 服务总线的模板代码。
可以随时将 Web角色或工作角色添加到现有的云服务。 用户可以选择在解决方案中添加现有项目或创建新项目。
云服务可以包含用不同语言实现的角色。 例如,您可以使用 Django 实现 Python Web 角色,或者使用 Python 或 C# 实现工作角色。 可以通过使用服务总线队列或存储队列来轻松地在角色之间进行通信。
在云服务上安装 Python
警告
在本文上次更新时与 Visual Studio 一起安装的安装脚本无法使用。 本部分介绍一种解决方法。
安装脚本的主要问题在于无法安装 Python。 首先,请在 ServiceDefinition.csdef 文件中定义两个启动任务。 第一个任务 (PrepPython.ps1) 下载并安装 Python 运行时。 第二个任务 (PipInstaller.ps1) 运行 pip,安装可能存在的任何依赖项。
以下脚本是针对 Python 3.8 编写的。 要使用 2.x 版 Python,请针对两个启动任务以及运行时任务将 PYTHON2 变量文件设置为 on:<Variable name="PYTHON2" value="<mark>on</mark>" />
。
<Startup>
<Task executionContext="elevated" taskType="simple" commandLine="bin\ps.cmd PrepPython.ps1">
<Environment>
<Variable name="EMULATED">
<RoleInstanceValue xpath="/RoleEnvironment/Deployment/@emulated" />
</Variable>
<Variable name="PYTHON2" value="off" />
</Environment>
</Task>
<Task executionContext="elevated" taskType="simple" commandLine="bin\ps.cmd PipInstaller.ps1">
<Environment>
<Variable name="EMULATED">
<RoleInstanceValue xpath="/RoleEnvironment/Deployment/@emulated" />
</Variable>
<Variable name="PYTHON2" value="off" />
</Environment>
</Task>
</Startup>
必须将 PYTHON2 和 PYPATH 变量添加到工作者启动任务。 仅当 PYTHON2 变量设置为 on 时,才使用 PYPATH 变量。
<Runtime>
<Environment>
<Variable name="EMULATED">
<RoleInstanceValue xpath="/RoleEnvironment/Deployment/@emulated" />
</Variable>
<Variable name="PYTHON2" value="off" />
<Variable name="PYPATH" value="%SystemDrive%\Python27" />
</Environment>
<EntryPoint>
<ProgramEntryPoint commandLine="bin\ps.cmd LaunchWorker.ps1" setReadyOnProcessStart="true" />
</EntryPoint>
</Runtime>
ServiceDefinition.csdef 示例
<?xml version="1.0" encoding="utf-8"?>
<ServiceDefinition name="AzureCloudServicePython" xmlns="http://schemas.microsoft.com/ServiceHosting/2008/10/ServiceDefinition" schemaVersion="2015-04.2.6">
<WorkerRole name="WorkerRole1" vmsize="Small">
<ConfigurationSettings>
<Setting name="Microsoft.WindowsAzure.Plugins.Diagnostics.ConnectionString" />
<Setting name="Python2" />
</ConfigurationSettings>
<Startup>
<Task executionContext="elevated" taskType="simple" commandLine="bin\ps.cmd PrepPython.ps1">
<Environment>
<Variable name="EMULATED">
<RoleInstanceValue xpath="/RoleEnvironment/Deployment/@emulated" />
</Variable>
<Variable name="PYTHON2" value="off" />
</Environment>
</Task>
<Task executionContext="elevated" taskType="simple" commandLine="bin\ps.cmd PipInstaller.ps1">
<Environment>
<Variable name="EMULATED">
<RoleInstanceValue xpath="/RoleEnvironment/Deployment/@emulated" />
</Variable>
<Variable name="PYTHON2" value="off" />
</Environment>
</Task>
</Startup>
<Runtime>
<Environment>
<Variable name="EMULATED">
<RoleInstanceValue xpath="/RoleEnvironment/Deployment/@emulated" />
</Variable>
<Variable name="PYTHON2" value="off" />
<Variable name="PYPATH" value="%SystemDrive%\Python27" />
</Environment>
<EntryPoint>
<ProgramEntryPoint commandLine="bin\ps.cmd LaunchWorker.ps1" setReadyOnProcessStart="true" />
</EntryPoint>
</Runtime>
<Imports>
<Import moduleName="RemoteAccess" />
<Import moduleName="RemoteForwarder" />
</Imports>
</WorkerRole>
</ServiceDefinition>
接下来,在角色的 ./bin 文件夹中创建 PrepPython.ps1 和 PipInstaller.ps1 文件。
PrepPython.ps1
此脚本安装 Python。 如果“PYTHON2”环境变量设置为“开”,则安装 Python 2.7,否则安装 Python 3.8 。
[Net.ServicePointManager]::SecurityProtocol = "tls12, tls11, tls"
$is_emulated = $env:EMULATED -eq "true"
$is_python2 = $env:PYTHON2 -eq "on"
$nl = [Environment]::NewLine
if (-not $is_emulated){
Write-Output "Checking if Python is installed...$nl"
if ($is_python2) {
& "${env:SystemDrive}\Python27\python.exe" -V | Out-Null
}
else {
py -V | Out-Null
}
if (-not $?) {
$url = "https://www.python.org/ftp/python/3.8.8/python-3.8.8-amd64.exe"
$outFile = "${env:TEMP}\python-3.8.8-amd64.exe"
if ($is_python2) {
$url = "https://www.python.org/ftp/python/2.7.18/python-2.7.18.amd64.msi"
$outFile = "${env:TEMP}\python-2.7.18.amd64.msi"
}
Write-Output "Not found, downloading $url to $outFile$nl"
Invoke-WebRequest $url -OutFile $outFile
Write-Output "Installing$nl"
if ($is_python2) {
Start-Process msiexec.exe -ArgumentList "/q", "/i", "$outFile", "ALLUSERS=1" -Wait
}
else {
Start-Process "$outFile" -ArgumentList "/quiet", "InstallAllUsers=1" -Wait
}
Write-Output "Done$nl"
}
else {
Write-Output "Already installed"
}
}
PipInstaller.ps1
此脚本调用 pip 并安装 requirements.txt 文件中的所有依赖项。 如果“PYTHON2”环境变量设置为“开”,则使用 Python 2.7,否则使用 Python 3.8 。
$is_emulated = $env:EMULATED -eq "true"
$is_python2 = $env:PYTHON2 -eq "on"
$nl = [Environment]::NewLine
if (-not $is_emulated){
Write-Output "Checking if requirements.txt exists$nl"
if (Test-Path ..\requirements.txt) {
Write-Output "Found. Processing pip$nl"
if ($is_python2) {
& "${env:SystemDrive}\Python27\python.exe" -m pip install -r ..\requirements.txt
}
else {
py -m pip install -r ..\requirements.txt
}
Write-Output "Done$nl"
}
else {
Write-Output "Not found$nl"
}
}
修改 LaunchWorker.ps1
注释
对于辅助角色项目,需要 LauncherWorker.ps1 文件才能执行启动文件。 在 Web 角色项目中,启动文件则是在项目属性中定义的。
bin\LaunchWorker.ps1 最初是为了执行多种准备工作而创建的,但实际上并不起作用。 将该文件中的内容替换为以下脚本。
此脚本从 Python 项目调用 worker.py 文件。 如果“PYTHON2”环境变量设置为“开”,则使用 Python 2.7,否则使用 Python 3.8 。
$is_emulated = $env:EMULATED -eq "true"
$is_python2 = $env:PYTHON2 -eq "on"
$nl = [Environment]::NewLine
if (-not $is_emulated)
{
Write-Output "Running worker.py$nl"
if ($is_python2) {
cd..
iex "$env:PYPATH\python.exe worker.py"
}
else {
cd..
iex "py worker.py"
}
}
else
{
Write-Output "Running (EMULATED) worker.py$nl"
# Customize to your local dev environment
if ($is_python2) {
cd..
iex "$env:PYPATH\python.exe worker.py"
}
else {
cd..
iex "py worker.py"
}
}
ps.cmd
Visual Studio 模板可能在 ./bin 文件夹中创建了一个 ps.cmd 文件。 此 shell 脚本调用前面的 PowerShell 包装脚本,并根据所调用 PowerShell 包装的名称提供日志记录。 如果未创建此文件,则以下脚本将位于其中:
@echo off
cd /D %~dp0
if not exist "%DiagnosticStore%\LogFiles" mkdir "%DiagnosticStore%\LogFiles"
%SystemRoot%\System32\WindowsPowerShell\v1.0\powershell.exe -ExecutionPolicy Unrestricted -File %* >> "%DiagnosticStore%\LogFiles\%~n1.txt" 2>> "%DiagnosticStore%\LogFiles\%~n1.err.txt"
在本地运行
如果将云服务项目设置为启动项目并按 F5,云服务会在本地 Azure 模拟器中运行。
虽然 PTVS 支持在模拟器中启动,但调试功能(例如断点)无法工作。
要调试 Web 角色和后台角色,可以将角色项目设置为启动项目,然后对其进行调试。 还可以设置多个启动项目。 右键单击解决方案并选择“设置启动项目”。
发布到 Azure
若要进行发布,请右键单击解决方案中的云服务项目,然后选择“发布”。
跟随向导。 如果需要,请启用远程桌面。 远程桌面可帮助调试某些功能。
完成配置设置后,请选择“发布”。
某些进度会显示在输出窗口中,然后会看到“Microsoft Azure 活动日志”窗口。
部署大约需要几分钟才能完成,然后 Web 和/或工作角色便会在 Azure 上运行!
查看日志
云服务虚拟机启动并安装 Python 后,可以查看日志,找出任何失败消息。 这些日志位于 C:\Resources\Directory\{role}\LogFiles 文件夹中。 从脚本尝试检测是否已安装 Python 时起,PrepPython.err.txt 中至少会包含一个错误,而 PipInstaller.err.txt 可能会指出 pip 版本已过时。
后续步骤
有关在 Python Tools for Visual Studio(PTVS)中使用 Web 和工作角色的更多详细信息,请参阅 PTVS 文档。
关于从 Web 角色和辅助角色中使用 Azure 服务(例如 Azure 存储或服务总线)的详细信息,请参阅以下文章: