51工具盒子

依楼听风雨
笑看云卷云舒,淡观潮起潮落

在Azure Functions中在运行时安装Python模块。

英文:

Install python module during runtime in Azure Functions

问题 {#heading}

我正在尝试在Azure Functions运行时安装Python模块/包,但运气不太好。使用pip安装模块似乎工作得很好,但让函数(当前的Python解释器)意识到已经安装了新模块却相当棘手。

以下是重现此问题的最小代码:

import io
import json
import logging
import sys

import azure.functions as func

app = func.FunctionApp(http_auth_level=func.AuthLevel.ANONYMOUS)

@app.route(route="InstallModule")
def install_module(req: func.HttpRequest) -> func.HttpResponse:
    logging.info("install_module was triggered")
    data = req.get_json()
    module_name = data.get("module")

    output = None
    try:
        import subprocess
        output = subprocess.run("pip install " + module_name, shell=True, check=True, capture_output=True)
        logging.info(output)
        __import__(module_name)
        output = f"{output}\nwe have survived this"
    except Exception as ex:
        logging.error(f"Failed to execute got {ex}")

    return func.HttpResponse(str(output))

第一次触发端点时,使用以下POST请求和JSON主体:

{
    "module": "numpy"
}

输出看起来是这样的:

Defaulting to user installation because normal site-packages is not writeable
Collecting numpy
  Downloading numpy-1.25.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (18.2 MB)
  ...
Successfully installed numpy-1.25.2

下一次:

Defaulting to user installation because normal site-packages is not writeable
Requirement already satisfied: numpy in /home/.local/lib/python3.10/site-packages (1.25.2)

但在两种情况下都将出现错误:

[Error]   Failed to execute got No module named 'numpy'

在本地运行相同的Azure函数没有问题,因此这与Azure Functions的缓存或权限有关...有没有办法克服这个问题?

另外,看起来Azure Functions没有使用虚拟环境,并且pip安装目录在路径中:

    "pip_V": "b'pip 23.0.1 from /usr/local/lib/python3.10/site-packages/pip (python 3.10)\\n'",
    "sys_path": [
        "/tmp/functions/standby/wwwroot",
        "/home/site/wwwroot/.python_packages/lib/site-packages",
        "/azure-functions-host/workers/python/3.10/LINUX/X64",
        "/usr/local/lib/python310.zip",
        "/usr/local/lib/python3.10",
        "/usr/local/lib/python3.10/lib-dynload",
        "/usr/local/lib/python3.10/site-packages",
        "/home/site/wwwroot"
    ],

我尝试过检查Python路径,在之前和之后运行pip freeze,并验证模块确实被安装,但我无法让Python解释器意识到模块已安装。

编辑 2023年10月8日

嗨,@Sampath,非常感谢您尝试帮助我解决这个问题。不幸的是,问题仍然存在,我创建了一个全新的项目,并复制了一切(如果您想分享项目,请告诉我)。第一次运行时,我获得了:

在Azure Functions中在运行时安装Python模块。

但第二次我得到了:

在Azure Functions中在运行时安装Python模块。

我不禁想知道我们的设置有什么不同?是项目设置还是我创建Azure Functions App的方式不同吗?顺便说一下,我尝试了托管选项:消耗和应用服务,两种选项的行为都相同。

在Azure Functions中在运行时安装Python模块。 英文:

I'm trying to install python module/package during runtime in Azure functions without too much luck.
Installing the module with pip seems to work just fine, but getting the function (current python interpreter) to realize a new module has been isntalled is proving to be rather tricky.

This is minimum code to reproduce the issue::

import io
import json
import logging
import sys

import azure.functions as func

app = func.FunctionApp(http_auth_level=func.AuthLevel.ANONYMOUS)

@app.route(route="InstallModule")
def install_module(req: func.HttpRequest) -> func.HttpResponse:
    logging.info("install_module was triggered")
    data = req.get_json()
    module_name = data.get("module")

    output = None
    try:
        import subprocess
        output = subprocess.run("pip install " + module_name, shell=True, check=True, capture_output=True)
        logging.info(output)
        __import__(module_name)
        output = f"{output}\nwe have survived this"
    except Exception as ex:
        logging.error(f"Failed to execute got {ex}")

    return func.HttpResponse(str(output))

The first time the endpoint is triggerd with: POST <azure url>/api/InstallModule w json body:

{
    &quot;module&quot;: &quot;numpy&quot;
}

the output looks something like:

Defaulting to user installation because normal site-packages is not writeable\nCollecting numpy\n  Downloading numpy-1.25.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (18.2 MB)\n     \xe2\x94\x81\xe2\x94\x81\xe2\x94\x81\xe2\x94\x81\xe2\x94\x81\xe2\x94\x81\xe2\x94\x81\xe2\x94\x81\xe2\x94\x81\xe2\x94\x81\xe2\x94\x81\xe2\x94\x81\xe2\x94\x81\xe2\x94\x81\xe2\x94\x81\xe2\x94\x81\xe2\x94\x81\xe2\x94\x81\xe2\x94\x81\xe2\x94\x81\xe2\x94\x81\xe2\x94\x81\xe2\x94\x81\xe2\x94\x81\xe2\x94\x81\xe2\x94\x81\xe2\x94\x81\xe2\x94\x81\xe2\x94\x81\xe2\x94\x81\xe2\x94\x81\xe2\x94\x81\xe2\x94\x81\xe2\x94\x81\xe2\x94\x81\xe2\x94\x81\xe2\x94\x81\xe2\x94\x81\xe2\x94\x81\xe2\x94\x81 18.2/18.2 MB 42.9 MB/s eta 0:00:00\nInstalling collected packages: numpy\nSuccessfully installed numpy-1.25.2\n

next time:

Defaulting to user installation because normal site-packages is not writeable\nRequirement already satisfied: numpy in /home/.local/lib/python3.10/site-packages (1.25.2)\n

But in both cases it will fail with error:

[Error]   Failed to execute got No module named &#39;numpy&#39;

Runninc the same azure function localy works without issue, so it has to do something with the cacheing or permissions on the Azure Functions... Any ideas how to overcome this issue?

BTW it looks like azure functions are not using virtual environment, and pip install directory is in path:

    &quot;pip_V&quot;: &quot;b&#39;pip 23.0.1 from /usr/local/lib/python3.10/site-packages/pip (python 3.10)\\n&#39;&quot;,
    &quot;sys_path&quot;: [
        &quot;/tmp/functions\\standby\\wwwroot&quot;,
        &quot;/home/site/wwwroot/.python_packages/lib/site-packages&quot;,
        &quot;/azure-functions-host/workers/python/3.10/LINUX/X64&quot;,
        &quot;/usr/local/lib/python310.zip&quot;,
        &quot;/usr/local/lib/python3.10&quot;,
        &quot;/usr/local/lib/python3.10/lib-dynload&quot;,
        &quot;/usr/local/lib/python3.10/site-packages&quot;,
        &quot;/home/site/wwwroot&quot;
    ],

I have tried checking python path, running pip freeze before and after and verify that the module does get installed, but I couldn't make python interpterer realize that the module is installed.

EDIT 10.08.2023

Hi @Sampath thank you so much for trying to help me with this one. Unfortunately, the issue is still there, I have created an entirely new project and copied everything (your entire code if you would like me to share the project please let me know) and published it. The first time I run it I get the:
在Azure Functions中在运行时安装Python模块。

but the second time I'm getting:
在Azure Functions中在运行时安装Python模块。

I can't help but wonder what is different in our setups? Is it something in the project settings or in the way I have created Azure Functions App? btw I have tried hosting options: Consumption and App service and both options behave the same way.
在Azure Functions中在运行时安装Python模块。

答案1 {#1}

得分: 1

# 在 Azure Functions 中运行时安装 Python 模块

v1
```python
import  json
import  logging
import  sys
import  azure.functions  as  func
from  importlib  import  import_module

def  main(req:  func.HttpRequest)  ->  func.HttpResponse:
    try:
        req_body = req.get_json()
        if  'module'  in  req_body:
            module_name = req_body['module']
            # 尝试直接导入模块
            try:
                import_module(module_name)
                return  func.HttpResponse(f"模块 '{module_name}' 已经可用。")
            except  ImportError:
                pass
            # 使用 subprocess 安装模块
            output = install_module(module_name)
            return  func.HttpResponse(f"模块 '{module_name}' 安装成功。\n{output}")
        else:
            return  func.HttpResponse("JSON 负载中缺少 'module' 键。",  status_code=400)
    except  Exception  as  e:
        return  func.HttpResponse(f"发生错误: {str(e)}",  status_code=500)

def  install_module(module):
    try:
        import  subprocess
        output = subprocess.run([sys.executable,  "-m",  "pip",  "install",  module],  capture_output=True,  text=True,  check=True)
        return  output.stdout
    except  Exception  as  ex:
        return  f"执行失败: {ex}"

v2

import json
import logging
import sys
import subprocess
import azure.functions as func
from importlib import import_module

app = func.FunctionApp()

@app.function_name("HttpTrigger1")
@app.route(route="req")  # 在这里指定路由
def main(req: func.HttpRequest) -> func.HttpResponse:
    try:
        req_body = req.get_json()
        if 'module' in req_body:
            module_name = req_body['module']
            # 尝试直接导入模块
            try:
                import_module(module_name)
                return func.HttpResponse(f"模块 '{module_name}' 已经可用。")
            except ImportError:
                pass
            # 使用 subprocess 安装模块
            output = install_module(module_name)
            return func.HttpResponse(f"模块 '{module_name}' 安装成功。\n{output}")
        else:
            return func.HttpResponse("JSON 负载中缺少 'module' 键。", status_code=400)
    except Exception as e:
        return func.HttpResponse(f"发生错误: {str(e)}", status_code=500)

def install_module(module):
    try:
        output = subprocess.run([sys.executable, "-m", "pip", "install", module], capture_output=True, text=True, check=True)
        return output.stdout
    except Exception as ex:
        return f"执行失败: {ex}"

在本地:

在Azure Functions中在运行时安装Python模块。

在 Azure:

在Azure Functions中在运行时安装Python模块。

在 SSH:

在Azure Functions中在运行时安装Python模块。

<details>
<summary>英文:</summary>

Install python module during runtime in Azure Functions


v1


```python
import  json
import  logging
import  sys
import  azure.functions  as  func
from  importlib  import  import_module
def  main(req:  func.HttpRequest)  -&amp;gt;  func.HttpResponse:
try:
req_body = req.get_json()
if  &amp;#39;module&amp;#39;  in  req_body:
module_name = req_body[&amp;#39;module&amp;#39;]
# Try importing the module directly
try:
import_module(module_name)
return  func.HttpResponse(f&amp;quot;Module &amp;#39;{module_name}&amp;#39; already available.&amp;quot;)
except  ImportError:
pass
# Install the module using subprocess
output = install_module(module_name)
return  func.HttpResponse(f&amp;quot;Module &amp;#39;{module_name}&amp;#39; installed successfully.\n{output}&amp;quot;)
else:
return  func.HttpResponse(&amp;quot;Missing &amp;#39;module&amp;#39; key in JSON payload .&amp;quot;,  status_code=400)
except  Exception  as  e:
return  func.HttpResponse(f&amp;quot;An error occurred: {str(e)}&amp;quot;,  status_code=500)
def  install_module(module):
try:
import  subprocess
output = subprocess.run([sys.executable,  &amp;quot;-m&amp;quot;,  &amp;quot;pip&amp;quot;,  &amp;quot;install&amp;quot;,  module],  capture_output=True,  text=True,  check=True)
return  output.stdout
except  Exception  as  ex:
return  f&amp;quot;Failed to execute got {ex}&amp;quot;
</code></pre>
 <p>v2</p>
 <pre><code>import json
import logging
import sys
import subprocess
import azure.functions as func
from importlib import import_module

app = func.FunctionApp()

@app.function_name(&amp;quot;HttpTrigger1&amp;quot;)
@app.route(route=&amp;quot;req&amp;quot;)  # Specify the route here
def main(req: func.HttpRequest) -&amp;gt; func.HttpResponse:
    try:
        req_body = req.get_json()
        if &amp;#39;module&amp;#39; in req_body:
            module_name = req_body[&amp;#39;module&amp;#39;]
            
            # Try importing the module directly
            try:
                import_module(module_name)
                return func.HttpResponse(f&amp;quot;Module &amp;#39;{module_name}&amp;#39; already available.&amp;quot;)
            except ImportError:
                pass
            
            # Install the module using subprocess
            output = install_module(module_name)
            
            return func.HttpResponse(f&amp;quot;Module &amp;#39;{module_name}&amp;#39; installed successfully.\n{output}&amp;quot;)
        else:
            return func.HttpResponse(&amp;quot;Missing &amp;#39;module&amp;#39; key in JSON payload.&amp;quot;, status_code=400)
    except Exception as e:
        return func.HttpResponse(f&amp;quot;An error occurred: {str(e)}&amp;quot;, status_code=500)

def install_module(module):
    try:
        output = subprocess.run([sys.executable, &amp;quot;-m&amp;quot;, &amp;quot;pip&amp;quot;, &amp;quot;install&amp;quot;, module], capture_output=True, text=True, check=True)
        return output.stdout
    except Exception as ex:
        return f&amp;quot;Failed to execute got {ex}&amp;quot;

</code></pre>
 <p><img alt="在Azure Functions中在运行时安装Python模块。" decoding="async" src="https://i.imgur.com/we3ushf.png" alt="enter image description here"><br> <strong>In local:</strong></p>
 <p><img alt="在Azure Functions中在运行时安装Python模块。" decoding="async" src="http://static.51tbox.com/static/2024-11-29/col/c8a2112fb8d0e3338b1ac15a2b986116/2f049269ee454dfbad1320ec23c6c61b.png.jpg" alt="enter image description here"></p>
 <p><img alt="在Azure Functions中在运行时安装Python模块。" decoding="async" src="https://i.imgur.com/wJiKr3M.png" alt="enter image description here"><br> <strong>In Azure:</strong><br> <a href="http://static.51tbox.com/static/2024-11-29/col/c8a2112fb8d0e3338b1ac15a2b986116/7dac92dca59b41fa84421324d5d4e774.png.jpg" data-fancybox="gallery"><img alt="在Azure Functions中在运行时安装Python模块。" decoding="async" src="http://static.51tbox.com/static/2024-11-29/col/c8a2112fb8d0e3338b1ac15a2b986116/7dac92dca59b41fa84421324d5d4e774.png.jpg" alt="enter image description here"></a></p>
 <p><a href="http://static.51tbox.com/static/2024-11-29/col/c8a2112fb8d0e3338b1ac15a2b986116/0ab4c4e95fc243f3b087d40c8353ff90.png.jpg" data-fancybox="gallery"><img alt="在Azure Functions中在运行时安装Python模块。" decoding="async" src="http://static.51tbox.com/static/2024-11-29/col/c8a2112fb8d0e3338b1ac15a2b986116/0ab4c4e95fc243f3b087d40c8353ff90.png.jpg" alt="enter image description here"></a></p>
 <p><strong>In SSH:</strong><br> <a href="http://static.51tbox.com/static/2024-11-29/col/c8a2112fb8d0e3338b1ac15a2b986116/7f26d74d572645c389976f286ed1432e.png.jpg" data-fancybox="gallery"><img alt="在Azure Functions中在运行时安装Python模块。" decoding="async" src="http://static.51tbox.com/static/2024-11-29/col/c8a2112fb8d0e3338b1ac15a2b986116/7f26d74d572645c389976f286ed1432e.png.jpg" alt="enter image description here"></a></p>
 <p><a href="https://i.imgur.com/1BuLHxg.png" data-fancybox="gallery"><img alt="在Azure Functions中在运行时安装Python模块。" decoding="async" src="https://i.imgur.com/1BuLHxg.png" alt="enter image description here"></a></p>
 <p></p>
</div>

```
赞(2)
未经允许不得转载:工具盒子 » 在Azure Functions中在运行时安装Python模块。