简体   繁体   English

Azure Functions - 无法在被调用脚本中导入其他 Python 模块

[英]Azure Functions - Unable to import other python modules in called scripts

I have created a simple HTTP trigger-based azure function in python which is calling another python script to create a sample file in azure data lake gen 1. My solution structure is given below: -我在 python 中创建了一个简单的基于 HTTP 触发器的 azure 函数,它调用另一个 python 脚本在 azure 数据湖 gen 1 中创建一个示例文件。我的解决方案结构如下:-

在此处输入图片说明

Requirements.txt contains the following imports: - Requirements.txt 包含以下导入:-

  • azure-functions天蓝色函数
  • azure-mgmt-resource天蓝色管理资源
  • azure-mgmt-datalake-store azure-mgmt-datalake-store
  • azure-datalake-store azure-datalake-store

init.py初始化文件

import logging, os, sys

import azure.functions as func
import json

def main(req: func.HttpRequest) -> func.HttpResponse:
    logging.info('Python HTTP trigger function processed a request.')
    name = req.params.get('name')
    if not name:
        try:
            req_body = req.get_json()
        except ValueError:
            pass
        else:         
            name = req_body.get('name')

    if name:
        full_path_to_script = os.path.join(os.path.dirname( __file__ ) + '/Test.py')
        logging.info(f"Path: - {full_path_to_script}")
        os.system(f"python {full_path_to_script}")
        return func.HttpResponse(f"Hello {name}!")
    else:
        return func.HttpResponse(
             "Please pass a name on the query string or in the request body",
             status_code=400
        )

Test.py测试文件

import json
from azure.datalake.store import core, lib, multithread

directoryId = ''
applicationKey = ''
applicationId = ''
adlsCredentials = lib.auth(tenant_id = directoryId, client_secret = applicationKey, client_id = applicationId)
adlsClient = core.AzureDLFileSystem(adlsCredentials, store_name = '')

with adlsClient.open('stage1/largeFiles/TestFile.json', 'rb') as input_file:
    data = json.load(input_file)
    with adlsClient.open('stage1/largeFiles/Result.json', 'wb') as responseFile:
        responseFile.write(data)

Test.py is failing with an error that no module found azure.datalake.store Why other required modules are not working for Test.py since it is inside the same directory? Test.py 失败并显示没有找到模块的错误azure.datalake.store为什么其他必需的模块不适用于 Test.py,因为它在同一目录中?

在此处输入图片说明

pip freeze output: - pip 冻结输出:-

adal==1.2.2
azure-common==1.1.23
azure-datalake-store==0.0.48
azure-functions==1.0.4
azure-mgmt-datalake-nspkg==3.0.1
azure-mgmt-datalake-store==0.5.0
azure-mgmt-nspkg==3.0.2
azure-mgmt-resource==6.0.0
azure-nspkg==3.0.2
certifi==2019.9.11
cffi==1.13.2
chardet==3.0.4
cryptography==2.8
idna==2.8
isodate==0.6.0
msrest==0.6.10
msrestazure==0.6.2
oauthlib==3.1.0
pycparser==2.19
PyJWT==1.7.1
python-dateutil==2.8.1
requests==2.22.0
requests-oauthlib==1.3.0
six==1.13.0
urllib3==1.25.6

Problem问题

os.system(f"python {full_path_to_script}") from your functions project is causing the issue.您的函数项目中的os.system(f"python {full_path_to_script}")导致了该问题。

Azure Functions Runtime sets up the environment, along with modifying process level variables like os.path so that your function can load any dependencies you may have. Azure Functions Runtime 设置环境,同时修改os.path等进程级变量,以便您的函数可以加载您可能拥有的任何依赖项。 When you create a sub-process like that, not all information will flow through.当您创建这样的子流程时,并非所有信息都会流过。 Additionally, you will face issues with logging -- logs from test.py would not show up properly unless explicitly handled.此外,您将面临日志记录问题——除非明确处理,否则test.py日志将无法正确显示。

Importing works locally because you have all your requirements.txt modules installed and available to test.py .导入在本地工作,因为您已安装所有requirements.txt模块并可用于test.py This is not the case in Azure.在 Azure 中,情况并非如此。 After remotely building as part of publish, your modules are included as part of your code package published.作为发布的一部分进行远程构建后,您的模块将作为您发布的代码包的一部分包含在内。 It's not "installed" globally in the Azure environment per se.它本身并未在 Azure 环境中全局“安装”。

Solution解决方案

You shouldn't have to run your script like that.你不应该像那样运行你的脚本。 In the example above, you could import your test.py from your __init__.py file, and that should behave like it was called python test.py (at least in the case above).在上面的例子中,你可以从你的__init__.py文件中导入你的test.py ,它的行为应该就像它被称为python test.py (至少在上面的例子中)。 Is there a reason you'd want to do python test.py in a sub-process over importing it?您是否有理由想要在子进程中执行python test.py而不是导入它?

Here's the official guide on how you'd want to structure your app to import shared code -- https://docs.microsoft.com/en-us/azure/azure-functions/functions-reference-python#folder-structure这是有关如何构建应用程序以导入共享代码的官方指南 - https://docs.microsoft.com/en-us/azure/azure-functions/functions-reference-python#folder-structure

Side-Note边注

I think once you get through the import issue, you may also face problems with adlsClient.open('stage1/largeFiles/TestFile.json', 'rb') .我认为一旦您解决了import问题,您可能还会遇到adlsClient.open('stage1/largeFiles/TestFile.json', 'rb') We recommend following the developer guide above to structure your project and using __file__ to get the absolute path ( reference ).我们建议按照上面的开发人员指南来构建您的项目并使用__file__来获取绝对路径( 参考)。

For example --例如 -

import pathlib
with open(pathlib.Path(__file__).parent / 'stage1' / 'largeFiles' /' TestFile.json'):
....

Now, if you really want to make os.system(f"python {full_path_to_script}") work, we have workarounds to the import issue.现在,如果你真的想让os.system(f"python {full_path_to_script}")工作,我们有导入问题的解决方法。 But, I'd rather not recommend such approach unless you have a really compelling need for it.但是,我宁愿不推荐这种方法,除非您有非常迫切的需求。 :) :)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM