Не удается развернуть базовый Python 3.6 в Azure - web.config? - PullRequest
1 голос
/ 29 апреля 2019

В настоящее время я публикую очень простое приложение для фляг в Azure, и уже несколько дней у меня ничего не получается, несмотря на то, что я нашел в Google.

Моя архитектура довольно проста (я покажу ее ниже, потому что я не думаю, что это корень проблемы), и у меня есть файл web.config:

Файл "web.config":

<?xml version="1.0"?>
<configuration>
  <appSettings>
    <add key="WSGI_HANDLER" value="MentorQuestFlask.app"/>
    <add key="PYTHONPATH" value="D:\home\site\wwwroot"/>
    <add key="WSGI_LOG" value="D:\home\LogFiles\wfastcgi.log"/>
  </appSettings>
  <system.webServer>
    <handlers>
      <add name="PythonHandler" path="handler.fcgi" verb="*" modules="FastCgiModule" scriptProcessor="D:\home\python364x64\python.exe|D:\home\python364x64\wfastcgi.py" resourceType="Unspecified" requireAccess="Script"/>
    </handlers>
    <rewrite>
      <rules>
        <rule name="Static Files" stopProcessing="true">
          <conditions>
            <add input="true" pattern="false" />
          </conditions>
        </rule>
        <rule name="Configure Python" stopProcessing="true">
          <match url="(.*)" ignoreCase="false" />
          <conditions>
            <add input="{REQUEST_URI}" pattern="^/static/.*" ignoreCase="true" negate="true" />
          </conditions>
          <action type="Rewrite" url="handler.fcgi/{R:1}" appendQueryString="true" />
        </rule>
      </rules>
    </rewrite>
  </system.webServer>
</configuration>

В Azure я добавил расширение: Python 3.6.4 x64 Также, следуя другому потоку, я добавил Python 3.6 на вкладке конфигурации: изображение зоны конфигурации

Также в Path Mappings я добавил:

Расширение: fastCgi

Обработчик скриптов: D: \ home \ python362x86 \ python.exe

Аргумент: D: \ home \ python362x86 \ wfastcgi.py

И, наконец, в настройках приложения WEBSITE_USE_PLACEHOLDER установлен на 0.

Но ничего не работает. На сайте вижу следующую ошибку:

"Невозможно отобразить страницу, поскольку произошла внутренняя ошибка сервера."

Поэтому я использовал Kudu для отображения следующего (ниже этого текста)

Мой вопрос:

  1. Похоже, пакеты не установлены (ошибка флешки)
  2. Кажется, web.config настроен неправильно.

Я пробовал несколько разных конфигураций, но ни одна из них не работала, и у меня заканчиваются идеи ...

Спасибо за вашу помощь или советы?

С уважением,

Charles

Отчет Куду

Traceback (most recent call last):
  File "D:\home\python364x64\wfastcgi.py", line 791, in main
    env, handler = read_wsgi_handler(response.physical_path)
  File "D:\home\python364x64\wfastcgi.py", line 633, in read_wsgi_handler
    handler = get_wsgi_handler(os.getenv("WSGI_HANDLER"))
  File "D:\home\python364x64\wfastcgi.py", line 616, in get_wsgi_handler
    raise ValueError('"%s" could not be imported%s' % (handler_name, last_tb))
ValueError: "MentorQuestFlask.app" could not be imported: Traceback (most recent call last):
  File "D:\home\python364x64\wfastcgi.py", line 600, in get_wsgi_handler
    handler = __import__(module_name, fromlist=[name_list[0][0]])
  File ".\MentorQuestFlask\__init__.py", line 5, in <module>
    from flask import Flask
ModuleNotFoundError: No module named 'flask'



StdOut: 

StdErr: 
2019-04-29 11:40:01.418920: Unhandled exception in wfastcgi.py: Traceback (most recent call last):
  File "D:\home\python364x64\wfastcgi.py", line 791, in main
    env, handler = read_wsgi_handler(response.physical_path)
  File "D:\home\python364x64\wfastcgi.py", line 633, in read_wsgi_handler
    handler = get_wsgi_handler(os.getenv("WSGI_HANDLER"))
  File "D:\home\python364x64\wfastcgi.py", line 616, in get_wsgi_handler
    raise ValueError('"%s" could not be imported%s' % (handler_name, last_tb))
ValueError: "MentorQuestFlask.app" could not be imported: Traceback (most recent call last):
  File "D:\home\python364x64\wfastcgi.py", line 600, in get_wsgi_handler
    handler = __import__(module_name, fromlist=[name_list[0][0]])
  File ".\MentorQuestFlask\__init__.py", line 5, in <module>
    from flask import Flask
ModuleNotFoundError: No module named 'flask'

2019-04-29 11:40:01.433762: Running on_exit tasks
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> 
<html xmlns="http://www.w3.org/1999/xhtml"> 
<head> 
<title>IIS Detailed Error - 500.0 - Internal Server Error</title> 
<style type="text/css"> 
<!-- 
body{margin:0;font-size:.7em;font-family:Verdana,Arial,Helvetica,sans-serif;} 
code{margin:0;color:#006600;font-size:1.1em;font-weight:bold;} 
.config_source code{font-size:.8em;color:#000000;} 
pre{margin:0;font-size:1.4em;word-wrap:break-word;} 
ul,ol{margin:10px 0 10px 5px;} 
ul.first,ol.first{margin-top:5px;} 
fieldset{padding:0 15px 10px 15px;word-break:break-all;} 
.summary-container fieldset{padding-bottom:5px;margin-top:4px;} 
legend.no-expand-all{padding:2px 15px 4px 10px;margin:0 0 0 -12px;} 
legend{color:#333333;;margin:4px 0 8px -12px;_margin-top:0px; 
font-weight:bold;font-size:1em;} 
a:link,a:visited{color:#007EFF;font-weight:bold;} 
a:hover{text-decoration:none;} 
h1{font-size:2.4em;margin:0;color:#FFF;} 
h2{font-size:1.7em;margin:0;color:#CC0000;} 
h3{font-size:1.4em;margin:10px 0 0 0;color:#CC0000;} 
h4{font-size:1.2em;margin:10px 0 5px 0; 
}#header{width:96%;margin:0 0 0 0;padding:6px 2% 6px 2%;font-family:"trebuchet MS",Verdana,sans-serif; 
color:#FFF;background-color:#5C87B2; 
}#content{margin:0 0 0 2%;position:relative;} 
.summary-container,.content-container{background:#FFF;width:96%;margin-top:8px;padding:10px;position:relative;} 
.content-container p{margin:0 0 10px 0; 
}#details-left{width:35%;float:left;margin-right:2%; 
}#details-right{width:63%;float:left;overflow:hidden; 
}#server_version{width:96%;_height:1px;min-height:1px;margin:0 0 5px 0;padding:11px 2% 8px 2%;color:#FFFFFF; 
background-color:#5A7FA5;border-bottom:1px solid #C1CFDD;border-top:1px solid #4A6C8E;font-weight:normal; 
font-size:1em;color:#FFF;text-align:right; 
}#server_version p{margin:5px 0;} 
table{margin:4px 0 4px 0;width:100%;border:none;} 
td,th{vertical-align:top;padding:3px 0;text-align:left;font-weight:normal;border:none;} 
th{width:30%;text-align:right;padding-right:2%;font-weight:bold;} 
thead th{background-color:#ebebeb;width:25%; 
}#details-right th{width:20%;} 
table tr.alt td,table tr.alt th{} 
.highlight-code{color:#CC0000;font-weight:bold;font-style:italic;} 
.clear{clear:both;} 
.preferred{padding:0 5px 2px 5px;font-weight:normal;background:#006633;color:#FFF;font-size:.8em;} 
--> 
</style> 

</head> 
<body> 
<div id="content"> 
<div class="content-container"> 
<h3>HTTP Error 500.0 - Internal Server Error</h3> 
<h4>The page cannot be displayed because an internal server error has occurred.</h4> 
</div> 
<div class="content-container"> 
<fieldset><h4>Most likely causes:</h4> 
<ul>    <li>IIS received the request; however, an internal error occurred during the processing of the request. The root cause of this error depends on which module handles the request and what was happening in the worker process when this error occurred.</li>    <li>IIS was not able to access the web.config file for the Web site or application. This can occur if the NTFS permissions are set incorrectly.</li>    <li>IIS was not able to process configuration for the Web site or application.</li>     <li>The authenticated user does not have permission to use this DLL.</li>   <li>The request is mapped to a managed handler but the .NET Extensibility Feature is not installed.</li> </ul> 
</fieldset> 
</div> 
<div class="content-container"> 
<fieldset><h4>Things you can try:</h4> 
<ul>    <li>Ensure that the NTFS permissions for the web.config file are correct and allow access to the Web server's machine account.</li>     <li>Check the event logs to see if any additional information was logged.</li>  <li>Verify the permissions for the DLL.</li>    <li>Install the .NET Extensibility feature if the request is mapped to a managed handler.</li>  <li>Create a tracing rule to track failed requests for this HTTP status code. For more information about creating a tracing rule for failed requests, click <a href="http://go.microsoft.com/fwlink/?LinkID=66439">here</a>. </li> </ul> 
</fieldset> 
</div> 

<div class="content-container"> 
<fieldset><h4>Detailed Error Information:</h4> 
<div id="details-left"> 
<table border="0" cellpadding="0" cellspacing="0"> 
<tr class="alt"><th>Module</th><td>&nbsp;&nbsp;&nbsp;FastCgiModule</td></tr> 
<tr><th>Notification</th><td>&nbsp;&nbsp;&nbsp;ExecuteRequestHandler</td></tr> 
<tr class="alt"><th>Handler</th><td>&nbsp;&nbsp;&nbsp;PythonHandler</td></tr> 
<tr><th>Error Code</th><td>&nbsp;&nbsp;&nbsp;0x00000000</td></tr> 

</table> 
</div> 
<div id="details-right"> 
<table border="0" cellpadding="0" cellspacing="0"> 
<tr class="alt"><th>Requested URL</th><td>&nbsp;&nbsp;&nbsp;https://mentor-quest:80/handler.fcgi/</td></tr> 
<tr><th>Physical Path</th><td>&nbsp;&nbsp;&nbsp;D:\home\site\wwwroot\handler.fcgi\</td></tr> 
<tr class="alt"><th>Logon Method</th><td>&nbsp;&nbsp;&nbsp;Anonymous</td></tr> 
<tr><th>Logon User</th><td>&nbsp;&nbsp;&nbsp;Anonymous</td></tr> 

</table> 
<div class="clear"></div> 
</div> 
</fieldset> 
</div> 

<div class="content-container"> 
<fieldset><h4>More Information:</h4> 
This error means that there was a problem while processing the request. The request was received by the Web server, but during processing a fatal error occurred, causing the 500 error. 
<p><a href="http://go.microsoft.com/fwlink/?LinkID=62293&amp;IIS70Error=500,0,0x00000000,14393">View more information &raquo;</a></p> 
<p>Microsoft Knowledge Base Articles:</p> 

Ниже архитектура проекта

MentorQuest:

У меня есть файл require.txt со всеми пакетами

Файл: "runserver.py":

from os import environ
from MentorQuestFlask import app

if __name__ == '__main__':
    HOST = environ.get('SERVER_HOST', 'localhost')
    try:
        PORT = int(environ.get('SERVER_PORT', '5555'))
    except ValueError:
        PORT = 5555
    app.run(HOST, PORT)

MentorQuest> MentorQuestFlask:

Файл " init .py":

from flask import Flask
app = Flask(__name__)

import MentorQuestFlask.views

Файл: "view.py":

from MentorQuestFlask import app

@app.route('/')
@app.route('/home')
def home():
    return 'Hello World!'

1 Ответ

0 голосов
/ 30 апреля 2019

Я решил свою проблему

Чтобы быть ясным, я не уверен, где он ошибся в первом разделе, потому что я радикально изменил свой код. Я поставил свое решение, так как я действительно искал несколько дней, и это может кому-то помочь. Я не понимаю всего перечисленного ниже, но это работает, поэтому я собираюсь продолжить, основываясь на этой структуре

Итак:

  1. У меня все еще есть плагин Python
  2. Я переключил файл "runserver.py" ниже, используя учебное пособие:

    импорт ОС от официантки из приложения импорта MentorQuestFlask

    serve (app, host = "0.0.0.0", port = os.environ ["PORT"])

Я немного изменил файл "deploy.cmd" (см. Ниже)

А также значительно упрощает веб-конфигурацию:

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
 <system.webServer>
  <handlers>
   <add name="httpPlatformHandler" path="*" verb="*"
         modules="httpPlatformHandler" resourceType="Unspecified" />
  </handlers>

  <httpPlatform processPath="D:\home\python364x64\python.exe"
   arguments="runserver.py" requestTimeout="00:04:00" startupTimeLimit="120" startupRetryCount="3" stdoutLogEnabled="true">
   <environmentVariables>
        <environmentVariable name="PYTHONPATH" value="D:\home\site\wwwroot" />
        <environmentVariable name="PORT" value="%HTTP_PLATFORM_PORT%" />
   </environmentVariables>
  </httpPlatform>
 </system.webServer>
</configuration>

Ниже нового файла deploy.cmd

New @if "%SCM_TRACE_LEVEL%" NEQ "4" @echo off

:: ----------------------
:: KUDU Deployment Script
:: Version: 1.0.16
:: ----------------------

:: Prerequisites
:: -------------

:: Verify node.js installed
where node 2>nul >nul
IF %ERRORLEVEL% NEQ 0 (
  echo Missing node.js executable, please install node.js, if already installed make sure it can be reached from current environment.
  goto error
)

:: Setup
:: -----

setlocal enabledelayedexpansion

SET ARTIFACTS=%~dp0%..\artifacts

IF NOT DEFINED DEPLOYMENT_SOURCE (
  SET DEPLOYMENT_SOURCE=%~dp0%.
)

IF NOT DEFINED DEPLOYMENT_TARGET (
  SET DEPLOYMENT_TARGET=%ARTIFACTS%\wwwroot
)

IF NOT DEFINED NEXT_MANIFEST_PATH (
  SET NEXT_MANIFEST_PATH=%ARTIFACTS%\manifest

  IF NOT DEFINED PREVIOUS_MANIFEST_PATH (
    SET PREVIOUS_MANIFEST_PATH=%ARTIFACTS%\manifest
  )
)

IF NOT DEFINED KUDU_SYNC_CMD (
  :: Install kudu sync
  echo Installing Kudu Sync
  call npm install kudusync -g --silent
  IF !ERRORLEVEL! NEQ 0 goto error

  :: Locally just running "kuduSync" would also work
  SET KUDU_SYNC_CMD=%appdata%\npm\kuduSync.cmd
)
goto Deployment

:: Utility Functions
:: -----------------

:SelectPythonVersion

IF DEFINED KUDU_SELECT_PYTHON_VERSION_CMD (
  call %KUDU_SELECT_PYTHON_VERSION_CMD% "%DEPLOYMENT_SOURCE%" "%DEPLOYMENT_TARGET%" "%DEPLOYMENT_TEMP%"
  IF !ERRORLEVEL! NEQ 0 goto error

  SET /P PYTHON_RUNTIME=<"%DEPLOYMENT_TEMP%\__PYTHON_RUNTIME.tmp"
  IF !ERRORLEVEL! NEQ 0 goto error

  SET /P PYTHON_VER=<"%DEPLOYMENT_TEMP%\__PYTHON_VER.tmp"
  IF !ERRORLEVEL! NEQ 0 goto error

  SET /P PYTHON_EXE=<"%DEPLOYMENT_TEMP%\__PYTHON_EXE.tmp"
  IF !ERRORLEVEL! NEQ 0 goto error

  SET /P PYTHON_ENV_MODULE=<"%DEPLOYMENT_TEMP%\__PYTHON_ENV_MODULE.tmp"
  IF !ERRORLEVEL! NEQ 0 goto error
) ELSE (
  SET PYTHON_RUNTIME=python-2.7
  SET PYTHON_VER=2.7
  SET PYTHON_EXE=%SYSTEMDRIVE%\python27\python.exe
  SET PYTHON_ENV_MODULE=virtualenv
)

goto :EOF

::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
:: Deployment
:: ----------

:Deployment
echo Handling python deployment.

:: 1. KuduSync
IF /I "%IN_PLACE_DEPLOYMENT%" NEQ "1" (
  call :ExecuteCmd "%KUDU_SYNC_CMD%" -v 50 -f "%DEPLOYMENT_SOURCE%" -t "%DEPLOYMENT_TARGET%" -n "%NEXT_MANIFEST_PATH%" -p "%PREVIOUS_MANIFEST_PATH%" -i ".git;.hg;.deployment;deploy.cmd"
  IF !ERRORLEVEL! NEQ 0 goto error
)

IF NOT EXIST "%DEPLOYMENT_TARGET%\requirements.txt" goto postPython
IF EXIST "%DEPLOYMENT_TARGET%\.skipPythonDeployment" goto postPython

echo Detected requirements.txt.  You can skip Python specific steps with a .skipPythonDeployment file.

:: 2. Select Python version
call :SelectPythonVersion

pushd "%DEPLOYMENT_TARGET%"

:: 3. Create virtual environment
IF NOT EXIST "%DEPLOYMENT_TARGET%\env\azure.env.%PYTHON_RUNTIME%.txt" (
  IF EXIST "%DEPLOYMENT_TARGET%\env" (
    echo Deleting incompatible virtual environment.
    rmdir /q /s "%DEPLOYMENT_TARGET%\env"
    IF !ERRORLEVEL! NEQ 0 goto error
  )

  echo Creating %PYTHON_RUNTIME% virtual environment.
  %PYTHON_EXE% -m %PYTHON_ENV_MODULE% env
  IF !ERRORLEVEL! NEQ 0 goto error

  copy /y NUL "%DEPLOYMENT_TARGET%\env\azure.env.%PYTHON_RUNTIME%.txt" >NUL
) ELSE (
  echo Found compatible virtual environment.
)

:: 4. Install packages
echo Pip install requirements.
D:\home\python364x64\python.exe -m pip install -r requirements.txt
IF !ERRORLEVEL! NEQ 0 goto error

REM Add additional package installation here
REM -- Example --
REM env\scripts\easy_install pytz
REM IF !ERRORLEVEL! NEQ 0 goto error

:: 5. Copy web.config
IF EXIST "%DEPLOYMENT_SOURCE%\web.%PYTHON_VER%.config" (
  echo Overwriting web.config with web.%PYTHON_VER%.config
  copy /y "%DEPLOYMENT_SOURCE%\web.%PYTHON_VER%.config" "%DEPLOYMENT_TARGET%\web.config"
)

:: 6. Django collectstatic
IF EXIST "%DEPLOYMENT_TARGET%\manage.py" (
  IF EXIST "%DEPLOYMENT_TARGET%\env\lib\site-packages\django" (
    IF NOT EXIST "%DEPLOYMENT_TARGET%\.skipDjango" (
      echo Collecting Django static files. You can skip Django specific steps with a .skipDjango file.
      IF NOT EXIST "%DEPLOYMENT_TARGET%\static" (
        MKDIR "%DEPLOYMENT_TARGET%\static"
      )
      env\scripts\python manage.py collectstatic --noinput --clear
    )
  )
)

popd

:postPython

::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
goto end

:: Execute command routine that will echo out when error
:ExecuteCmd
setlocal
set _CMD_=%*
call %_CMD_%
if "%ERRORLEVEL%" NEQ "0" echo Failed exitCode=%ERRORLEVEL%, command=%_CMD_%
exit /b %ERRORLEVEL%

:error
endlocal
echo An error has occurred during web site deployment.
call :exitSetErrorLevel
call :exitFromFunction 2>nul

:exitSetErrorLevel
exit /b 1

:exitFromFunction
()

:end
endlocal
echo Finished successfully.

    @if "%SCM_TRACE_LEVEL%" NEQ "4" @echo off

    :: ----------------------
    :: KUDU Deployment Script
    :: Version: 1.0.16
    :: ----------------------

    :: Prerequisites
    :: -------------

    :: Verify node.js installed
    where node 2>nul >nul
    IF %ERRORLEVEL% NEQ 0 (
      echo Missing node.js executable, please install node.js, if already installed make sure it can be reached from current environment.
      goto error
    )

    :: Setup
    :: -----

    setlocal enabledelayedexpansion

    SET ARTIFACTS=%~dp0%..\artifacts

    IF NOT DEFINED DEPLOYMENT_SOURCE (
      SET DEPLOYMENT_SOURCE=%~dp0%.
    )

    IF NOT DEFINED DEPLOYMENT_TARGET (
      SET DEPLOYMENT_TARGET=%ARTIFACTS%\wwwroot
    )

    IF NOT DEFINED NEXT_MANIFEST_PATH (
      SET NEXT_MANIFEST_PATH=%ARTIFACTS%\manifest

      IF NOT DEFINED PREVIOUS_MANIFEST_PATH (
        SET PREVIOUS_MANIFEST_PATH=%ARTIFACTS%\manifest
      )
    )

    IF NOT DEFINED KUDU_SYNC_CMD (
      :: Install kudu sync
      echo Installing Kudu Sync
      call npm install kudusync -g --silent
      IF !ERRORLEVEL! NEQ 0 goto error

      :: Locally just running "kuduSync" would also work
      SET KUDU_SYNC_CMD=%appdata%\npm\kuduSync.cmd
    )
    goto Deployment

    :: Utility Functions
    :: -----------------

    :SelectPythonVersion

    IF DEFINED KUDU_SELECT_PYTHON_VERSION_CMD (
      call %KUDU_SELECT_PYTHON_VERSION_CMD% "%DEPLOYMENT_SOURCE%" "%DEPLOYMENT_TARGET%" "%DEPLOYMENT_TEMP%"
      IF !ERRORLEVEL! NEQ 0 goto error

      SET /P PYTHON_RUNTIME=<"%DEPLOYMENT_TEMP%\__PYTHON_RUNTIME.tmp"
      IF !ERRORLEVEL! NEQ 0 goto error

      SET /P PYTHON_VER=<"%DEPLOYMENT_TEMP%\__PYTHON_VER.tmp"
      IF !ERRORLEVEL! NEQ 0 goto error

      SET /P PYTHON_EXE=<"%DEPLOYMENT_TEMP%\__PYTHON_EXE.tmp"
      IF !ERRORLEVEL! NEQ 0 goto error

      SET /P PYTHON_ENV_MODULE=<"%DEPLOYMENT_TEMP%\__PYTHON_ENV_MODULE.tmp"
      IF !ERRORLEVEL! NEQ 0 goto error
    ) ELSE (
      SET PYTHON_RUNTIME=python-2.7
      SET PYTHON_VER=2.7
      SET PYTHON_EXE=%SYSTEMDRIVE%\python27\python.exe
      SET PYTHON_ENV_MODULE=virtualenv
    )

    goto :EOF

    ::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
    :: Deployment
    :: ----------

    :Deployment
    echo Handling python deployment.

    :: 1. KuduSync
    IF /I "%IN_PLACE_DEPLOYMENT%" NEQ "1" (
      call :ExecuteCmd "%KUDU_SYNC_CMD%" -v 50 -f "%DEPLOYMENT_SOURCE%" -t "%DEPLOYMENT_TARGET%" -n "%NEXT_MANIFEST_PATH%" -p "%PREVIOUS_MANIFEST_PATH%" -i ".git;.hg;.deployment;deploy.cmd"
      IF !ERRORLEVEL! NEQ 0 goto error
    )

    IF NOT EXIST "%DEPLOYMENT_TARGET%\requirements.txt" goto postPython
    IF EXIST "%DEPLOYMENT_TARGET%\.skipPythonDeployment" goto postPython

    echo Detected requirements.txt.  You can skip Python specific steps with a .skipPythonDeployment file.

    :: 2. Select Python version
    call :SelectPythonVersion

    pushd "%DEPLOYMENT_TARGET%"

    :: 3. Create virtual environment
    IF NOT EXIST "%DEPLOYMENT_TARGET%\env\azure.env.%PYTHON_RUNTIME%.txt" (
      IF EXIST "%DEPLOYMENT_TARGET%\env" (
        echo Deleting incompatible virtual environment.
        rmdir /q /s "%DEPLOYMENT_TARGET%\env"
        IF !ERRORLEVEL! NEQ 0 goto error
      )

      echo Creating %PYTHON_RUNTIME% virtual environment.
      %PYTHON_EXE% -m %PYTHON_ENV_MODULE% env
      IF !ERRORLEVEL! NEQ 0 goto error

      copy /y NUL "%DEPLOYMENT_TARGET%\env\azure.env.%PYTHON_RUNTIME%.txt" >NUL
    ) ELSE (
      echo Found compatible virtual environment.
    )

    :: 4. Install packages
    echo Pip install requirements.
    D:\home\python364x64\python.exe -m pip install -r requirements.txt
    IF !ERRORLEVEL! NEQ 0 goto error

    REM Add additional package installation here
    REM -- Example --
    REM env\scripts\easy_install pytz
    REM IF !ERRORLEVEL! NEQ 0 goto error

    :: 5. Copy web.config
    IF EXIST "%DEPLOYMENT_SOURCE%\web.%PYTHON_VER%.config" (
      echo Overwriting web.config with web.%PYTHON_VER%.config
      copy /y "%DEPLOYMENT_SOURCE%\web.%PYTHON_VER%.config" "%DEPLOYMENT_TARGET%\web.config"
    )

    :: 6. Django collectstatic
    IF EXIST "%DEPLOYMENT_TARGET%\manage.py" (
      IF EXIST "%DEPLOYMENT_TARGET%\env\lib\site-packages\django" (
        IF NOT EXIST "%DEPLOYMENT_TARGET%\.skipDjango" (
          echo Collecting Django static files. You can skip Django specific steps with a .skipDjango file.
          IF NOT EXIST "%DEPLOYMENT_TARGET%\static" (
            MKDIR "%DEPLOYMENT_TARGET%\static"
          )
          env\scripts\python manage.py collectstatic --noinput --clear
        )
      )
    )

    popd

    :postPython

    ::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
    goto end

    :: Execute command routine that will echo out when error
    :ExecuteCmd
    setlocal
    set _CMD_=%*
    call %_CMD_%
    if "%ERRORLEVEL%" NEQ "0" echo Failed exitCode=%ERRORLEVEL%, command=%_CMD_%
    exit /b %ERRORLEVEL%

    :error
    endlocal
    echo An error has occurred during web site deployment.
    call :exitSetErrorLevel
    call :exitFromFunction 2>nul

    :exitSetErrorLevel
    exit /b 1

    :exitFromFunction
    ()

    :end
    endlocal
    echo Finished successfully.
...