英文:
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 App的方式不同吗?顺便说一下,我尝试了托管选项:消耗和应用服务,两种选项的行为都相同。
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:
{
"module": "numpy"
}
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 'numpy'
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:
"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"
],
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:
but the second time I'm getting:
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.
答案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:
在 SSH:
<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) -&gt; func.HttpResponse:
try:
req_body = req.get_json()
if &#39;module&#39; in req_body:
module_name = req_body[&#39;module&#39;]
# Try importing the module directly
try:
import_module(module_name)
return func.HttpResponse(f&quot;Module &#39;{module_name}&#39; already available.&quot;)
except ImportError:
pass
# Install the module using subprocess
output = install_module(module_name)
return func.HttpResponse(f&quot;Module &#39;{module_name}&#39; installed successfully.\n{output}&quot;)
else:
return func.HttpResponse(&quot;Missing &#39;module&#39; key in JSON payload .&quot;, status_code=400)
except Exception as e:
return func.HttpResponse(f&quot;An error occurred: {str(e)}&quot;, status_code=500)
def install_module(module):
try:
import subprocess
output = subprocess.run([sys.executable, &quot;-m&quot;, &quot;pip&quot;, &quot;install&quot;, module], capture_output=True, text=True, check=True)
return output.stdout
except Exception as ex:
return f&quot;Failed to execute got {ex}&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(&quot;HttpTrigger1&quot;)
@app.route(route=&quot;req&quot;) # Specify the route here
def main(req: func.HttpRequest) -&gt; func.HttpResponse:
try:
req_body = req.get_json()
if &#39;module&#39; in req_body:
module_name = req_body[&#39;module&#39;]
# Try importing the module directly
try:
import_module(module_name)
return func.HttpResponse(f&quot;Module &#39;{module_name}&#39; already available.&quot;)
except ImportError:
pass
# Install the module using subprocess
output = install_module(module_name)
return func.HttpResponse(f&quot;Module &#39;{module_name}&#39; installed successfully.\n{output}&quot;)
else:
return func.HttpResponse(&quot;Missing &#39;module&#39; key in JSON payload.&quot;, status_code=400)
except Exception as e:
return func.HttpResponse(f&quot;An error occurred: {str(e)}&quot;, status_code=500)
def install_module(module):
try:
output = subprocess.run([sys.executable, &quot;-m&quot;, &quot;pip&quot;, &quot;install&quot;, module], capture_output=True, text=True, check=True)
return output.stdout
except Exception as ex:
return f&quot;Failed to execute got {ex}&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>
```