用于 Visual Studio 的 Python 工具中的 Python Web 角色和辅助角色Python web and worker roles with Python Tools for Visual Studio

本文概述了如何在针对 Visual Studio 的 Python 工具中使用 Python Web 角色和辅助角色。This article provides an overview of using Python web and worker roles using Python Tools for Visual Studio. 介绍如何使用 Visual Studio 来创建和部署使用 Python 的基本云服务。Learn how to use Visual Studio to create and deploy a basic Cloud Service that uses Python.

先决条件Prerequisites

Note

若要完成本教程,需要一个 Azure 帐户。To complete this tutorial, you need an Azure account. 可以注册 试用版You can sign up for a trial.

什么是 Python Web 角色和辅助角色?What are Python web and worker roles?

Azure 提供了三种用于运行应用程序的计算模型:Azure 应用服务中的 Web 应用功能Azure 虚拟机Azure 云服务Azure provides three compute models for running applications: Web Apps feature in Azure App Service, Azure Virtual Machines, and Azure Cloud Services. 这三种模型都支持 Python。All three models support Python. 云服务(包括 Web 角色和辅助角色)提供了 平台即服务 (PaaS)Cloud Services, which include web and worker roles, provide Platform as a Service (PaaS). 在云服务中,Web 角色提供专用的 Internet Information Services (IIS) Web 服务器来托管前端 Web 应用程序,而辅助角色可独立于用户交互或输入运行异步任务、运行时间较长的任务或永久性任务。Within a cloud service, a web role provides a dedicated Internet Information Services (IIS) web server to host front end web applications, while a worker role can run asynchronous, long-running, or perpetual tasks independent of user interaction or input.

有关详细信息,请参阅 什么是云服务?For more information, see What is a Cloud Service?.

Note

想要构建一个简单的网站?Looking to build a simple website? 如果方案只涉及一个简单的网站前端,请考虑使用 Azure 应用服务中的轻型 Web 应用功能。If your scenario involves just a simple website front end, consider using the lightweight Web Apps feature in Azure App Service. 随着网站的不断扩大和需求的不断变化,用户可将其轻松升级到云服务。You can easily upgrade to a Cloud Service as your website grows and your requirements change. 请参阅 Python 开发人员中心关于如何在 Azure 应用服务中开发 Web 应用功能的文章。See the Python Developer Center for articles that cover development of the Web Apps feature in Azure App Service.

创建项目Project creation

在 Visual Studio 中,可以选择“新建项目”对话框中“Python”下的“Azure 云服务”。In Visual Studio, you can select Azure Cloud Service in the New Project dialog box, under Python.

“新建项目”对话框

在 Azure 云服务向导中,可以创建新的 Web 角色和辅助角色。In the Azure Cloud Service wizard, you can create new web and worker roles.

Azure 云服务对话框

辅助角色模板包含样板文件代码以连接到 Azure 存储帐户或 Azure 服务总线。The worker role template comes with boilerplate code to connect to an Azure storage account or Azure Service Bus.

云服务解决方案

可以随时将 Web 角色或辅助角色添加到现有的云服务。You can add web or worker roles to an existing cloud service at any time. 用户可以选择在解决方案中添加现有项目或创建新项目。You can choose to add existing projects in your solution, or create new ones.

添加角色命令

云服务可以包含用不同语言实现的角色。Your cloud service can contain roles implemented in different languages. 例如,可以使用 Django 实现 Python Web 角色,而用使用 Python 或 C# 实现辅助角色。For example, you can have a Python web role implemented using Django, with Python, or with C# worker roles. 可以通过使用服务总线队列或存储队列来轻松地在角色之间进行通信。You can easily communicate between your roles using Service Bus queues or storage queues.

在云服务上安装 PythonInstall Python on the cloud service

Warning

在本文上次更新时与 Visual Studio 一起安装的安装脚本无法使用。The setup scripts that are installed with Visual Studio (at the time this article was last updated) do not work. 本部分介绍一种解决方法。This section describes a workaround.

安装脚本的主要问题在于无法安装 Python。The main problem with the setup scripts is that they do not install python. 首先,请在 ServiceDefinition.csdef 文件中定义两个启动任务First, define two startup tasks in the ServiceDefinition.csdef file. 第一个任务 (PrepPython.ps1) 下载并安装 Python 运行时。The first task (PrepPython.ps1) downloads and installs the Python runtime. 第二个任务 (PipInstaller.ps1) 运行 pip,安装可能存在的任何依赖项。The second task (PipInstaller.ps1) runs pip to install any dependencies you may have.

以下脚本是针对 Python 3.5 编写的。The following scripts were written targeting Python 3.5. 要使用 2.x 版 Python,请针对两个启动任务以及运行时任务将 PYTHON2 变量文件设置为 on<Variable name="PYTHON2" value="<mark>on</mark>" />If you want to use the version 2.x of python, set the PYTHON2 variable file to on for the two startup tasks and the runtime task: <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 变量添加到辅助角色启动任务。The PYTHON2 and PYPATH variables must be added to the worker startup task. 仅当 PYTHON2 变量设置为 on 时,才使用 PYPATH 变量。The PYPATH variable is only used if the PYTHON2 variable is set to on.

<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 示例Sample 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.ps1PipInstaller.ps1 文件。Next, create the PrepPython.ps1 and PipInstaller.ps1 files in the ./bin folder of your role.

PrepPython.ps1PrepPython.ps1

此脚本安装 Python。This script installs python. 如果 PYTHON2 环境变量设置为 on,则安装 Python 2.7,否则安装 Python 3.5。If the PYTHON2 environment variable is set to on, then Python 2.7 is installed, otherwise Python 3.5 is installed.

[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.5.2/python-3.5.2-amd64.exe"
        $outFile = "${env:TEMP}\python-3.5.2-amd64.exe"

        if ($is_python2) {
            $url = "https://www.python.org/ftp/python/2.7.12/python-2.7.12.amd64.msi"
            $outFile = "${env:TEMP}\python-2.7.12.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.ps1PipInstaller.ps1

此脚本调用 pip 并安装 requirements.txt 文件中的所有依赖项。This script calls up pip and installs all of the dependencies in the requirements.txt file. 如果 PYTHON2 环境变量设置为 on,则使用 Python 2.7,否则使用 Python 3.5。If the PYTHON2 environment variable is set to on, then Python 2.7 is used, otherwise Python 3.5 is used.

$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.ps1Modify LaunchWorker.ps1

Note

对于辅助角色项目,需要 LauncherWorker.ps1 文件才能执行启动文件。In the case of a worker role project, LauncherWorker.ps1 file is required to execute the startup file. 在“Web 角色” 项目中,会在项目属性中定义该启动文件。In a web role project, the startup file is instead defined in the project properties.

bin\LaunchWorker.ps1 最初是为了执行多种准备工作而创建的,但实际上并不起作用。The bin\LaunchWorker.ps1 was originally created to do a lot of prep work but it doesn't really work. 将该文件中的内容替换为以下脚本。Replace the contents in that file with the following script.

此脚本从 Python 项目调用 worker.py 文件。This script calls the worker.py file from your python project. 如果 PYTHON2 环境变量设置为 on,则使用 Python 2.7,否则使用 Python 3.5。If the PYTHON2 environment variable is set to on, then Python 2.7 is used, otherwise Python 3.5 is used.

$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.cmdps.cmd

Visual Studio 模板应在 ./bin 文件夹中创建了一个 ps.cmd 文件。The Visual Studio templates should have created a ps.cmd file in the ./bin folder. 此 shell 脚本调用上述 PowerShell 包装脚本,并根据所调用 PowerShell 包装的名称提供日志记录。This shell script calls out the PowerShell wrapper scripts above and provides logging based on the name of the PowerShell wrapper called. 如果未创建此文件,请注意,下面是该文件应该包含的内容。If this file wasn't created, here is what should be in it.

@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"

在本地运行Run locally

如果将云服务项目设置为启动项目并按 F5,云服务会在本地 Azure 模拟器中运行。If you set your cloud service project as the startup project and press F5, the cloud service runs in the local Azure emulator.

虽然 PTVS 支持在模拟器中启动,调试(例如断点)将无法工作。Although PTVS supports launching in the emulator, debugging (for example, breakpoints) does not work.

要调试 Web 角色和辅助角色,可以将角色项目设置为启动项目并对其进行调试。To debug your web and worker roles, you can set the role project as the startup project and debug that instead. 还可以设置多个启动项目。You can also set multiple startup projects. 右键单击解决方案并选择“设置启动项目”。Right-click the solution and then select Set StartUp Projects.

解决方案启动项目属性

发布到 AzurePublish to Azure

要进行发布,请右键单击解决方案中的云服务项目,并选择“发布”。To publish, right-click the cloud service project in the solution and then select Publish.

Azure 发布登录

遵循向导操作。Follow the wizard. 如果需要,请启用远程桌面。If you need to, enable remote desktop. 远程桌面可帮助调试某些功能。Remote desktop is helpful when you need to debug something.

完成配置设置后,单击 发布When you are done configuring settings, click Publish.

某些进度会显示在输出窗口中,然后会看到“Azure 活动日志”窗口。Some progress appears in the output window, then you'll see the Azure Activity Log window.

Microsoft  Azure 活动日志窗口

部署需要几分钟才能完成,然后 Web 和/或辅助角色会在 Azure 上运行!Deployment takes several minutes to complete, then your web and/or worker roles run on Azure!

查看日志Investigate logs

云服务虚拟机启动并安装 Python 后,可以查看日志,找出任何失败消息。After the cloud service virtual machine starts up and installs Python, you can look at the logs to find any failure messages. 这些日志位于 C:\Resources\Directory\{role}\LogFiles 文件夹中。These logs are located in the C:\Resources\Directory\{role}\LogFiles folder. 从脚本尝试检测是否已安装 Python 时起,PrepPython.err.txt 中至少会包含一个错误,而 PipInstaller.err.txt 可能会指出 pip 版本已过时。PrepPython.err.txt has at least one error in it from when the script tries to detect if Python is installed and PipInstaller.err.txt may complain about an outdated version of pip.

后续步骤Next steps

有关在 Python Tools for Visual Studio 中使用 Web 角色和辅助角色的更多详细信息,请参阅 PTVS 文档:For more detailed information about working with web and worker roles in Python Tools for Visual Studio, see the PTVS documentation:

有关作为 Web 角色和辅助角色使用 Azure 服务(例如使用 Azure 存储或服务总线)的详细信息,请参阅以下文章:For more details about using Azure services from your web and worker roles, such as using Azure Storage or Service Bus, see the following articles: