【问题标题】:Trying to create a deployment file for AWS lambda尝试为 AWS lambda 创建部署文件
【发布时间】:2017-09-17 20:36:51
【问题描述】:

我正在尝试创建一个 Alexa 技能,它可以告诉我下一趟火车时间是在我的火车站。我想使用一个名为 pygtfs 的包,它是一个对以 Google 的通用运输提要规范 (GTFS) 格式存储的信息进行建模的库。我有处理从 alexa 发送的 json 对象的文件,它们工作正常。我无法制作要上传到 aws lambda 的 zip 部署包。我有一个创建部署包的 python 脚本,但出现错误。该错误未将正确的文件添加到部署包中。

def _copy_deployment_files(deployment_dir):
    for deployment_file in deployment_files:
        if os.path.exists(deployment_file):
            cmd = "cp{0}{1}".format(deployment_file, deployment_dir).split()
        --->return_code = subprocess.call(cmd, shell=False)<----
        else:
            raise NameError("Deployment file not found [{0}]".format(deployment_file))

在 _copy_deployment_files 函数中已尝试将 subprocess 方法的 shell 参数设置为 true

return_code = subprocess.call(cmd, shell=True)

但不包括 AlexaBaseHandler.py、AlexaDeploymentHandler.py 和 main.py。

我的问题是如何让 create_development 将 AlexaBaseHandler.py、AlexaDeploymentHandler.py 和 main.py 添加到部署包中,以及如何确保 pygtfs 包也安装到部署包中?

这是return_code = subprocess.call(cmd, shell=True)时的结果

    C:\ProgramData\Anaconda3\python.exe C:/Users/Owner/PycharmProjects/PatcoSchedule/create_deployment.py
Collecting requests==2.8.1
  Using cached requests-2.8.1-py2.py3-none-any.whl
Installing collected packages: requests
Successfully installed requests-2.8.1
Collecting sseclient==0.0.11
Collecting requests>=2.0.0 (from sseclient==0.0.11)
  Using cached requests-2.18.4-py2.py3-none-any.whl
Collecting six (from sseclient==0.0.11)
  Using cached six-1.11.0-py2.py3-none-any.whl
Collecting chardet<3.1.0,>=3.0.2 (from requests>=2.0.0->sseclient==0.0.11)
  Using cached chardet-3.0.4-py2.py3-none-any.whl
Collecting urllib3<1.23,>=1.21.1 (from requests>=2.0.0->sseclient==0.0.11)
  Using cached urllib3-1.22-py2.py3-none-any.whl
Collecting certifi>=2017.4.17 (from requests>=2.0.0->sseclient==0.0.11)
  Using cached certifi-2017.7.27.1-py2.py3-none-any.whl
Collecting idna<2.7,>=2.5 (from requests>=2.0.0->sseclient==0.0.11)
  Using cached idna-2.6-py2.py3-none-any.whl
Installing collected packages: chardet, urllib3, certifi, idna, requests, six, sseclient
Successfully installed certifi-2017.7.27.1 chardet-3.0.4 idna-2.6 requests-2.18.4 six-1.11.0 sseclient-0.0.11 urllib3-1.22
Target directory C:\Users\Owner\PycharmProjects\PatcoSchedule\deployments\deployment_15\requests already exists. Specify --upgrade to force replacement.
Collecting hammock==0.2.4
Collecting requests>=1.1.0 (from hammock==0.2.4)
  Using cached requests-2.18.4-py2.py3-none-any.whl
Collecting idna<2.7,>=2.5 (from requests>=1.1.0->hammock==0.2.4)
  Using cached idna-2.6-py2.py3-none-any.whl
Collecting urllib3<1.23,>=1.21.1 (from requests>=1.1.0->hammock==0.2.4)
  Using cached urllib3-1.22-py2.py3-none-any.whl
Collecting certifi>=2017.4.17 (from requests>=1.1.0->hammock==0.2.4)
  Using cached certifi-2017.7.27.1-py2.py3-none-any.whl
Collecting chardet<3.1.0,>=3.0.2 (from requests>=1.1.0->hammock==0.2.4)
  Using cached chardet-3.0.4-py2.py3-none-any.whl
Installing collected packages: idna, urllib3, certifi, chardet, requests, hammock
Successfully installed certifi-2017.7.27.1 chardet-3.0.4 hammock-0.2.4 idna-2.6 requests-2.18.4 urllib3-1.22
Target directory C:\Users\Owner\PycharmProjects\PatcoSchedule\deployments\deployment_15\certifi already exists. Specify --upgrade to force replacement.
Target directory C:\Users\Owner\PycharmProjects\PatcoSchedule\deployments\deployment_15\certifi-2017.7.27.1.dist-info already exists. Specify --upgrade to force replacement.
Target directory C:\Users\Owner\PycharmProjects\PatcoSchedule\deployments\deployment_15\chardet already exists. Specify --upgrade to force replacement.
Target directory C:\Users\Owner\PycharmProjects\PatcoSchedule\deployments\deployment_15\chardet-3.0.4.dist-info already exists. Specify --upgrade to force replacement.
Target directory C:\Users\Owner\PycharmProjects\PatcoSchedule\deployments\deployment_15\idna already exists. Specify --upgrade to force replacement.
Target directory C:\Users\Owner\PycharmProjects\PatcoSchedule\deployments\deployment_15\idna-2.6.dist-info already exists. Specify --upgrade to force replacement.
Target directory C:\Users\Owner\PycharmProjects\PatcoSchedule\deployments\deployment_15\requests already exists. Specify --upgrade to force replacement.
Target directory C:\Users\Owner\PycharmProjects\PatcoSchedule\deployments\deployment_15\requests-2.18.4.dist-info already exists. Specify --upgrade to force replacement.
Target directory C:\Users\Owner\PycharmProjects\PatcoSchedule\deployments\deployment_15\urllib3 already exists. Specify --upgrade to force replacement.
Target directory C:\Users\Owner\PycharmProjects\PatcoSchedule\deployments\deployment_15\urllib3-1.22.dist-info already exists. Specify --upgrade to force replacement.
Target directory C:\Users\Owner\PycharmProjects\PatcoSchedule\deployments\deployment_15\__pycache__ already exists. Specify --upgrade to force replacement.
Collecting pygtfs==0.1.3
  Using cached pygtfs-0.1.3-py2.py3-none-any.whl
Collecting sqlalchemy>=0.7.8 (from pygtfs==0.1.3)
  Using cached SQLAlchemy-1.1.14.tar.gz
Collecting six (from pygtfs==0.1.3)
  Using cached six-1.11.0-py2.py3-none-any.whl
Collecting pytz>=2012d (from pygtfs==0.1.3)
  Using cached pytz-2017.2-py2.py3-none-any.whl
Collecting docopt (from pygtfs==0.1.3)
Installing collected packages: sqlalchemy, six, pytz, docopt, pygtfs
  Running setup.py install for sqlalchemy: started
    Running setup.py install for sqlalchemy: finished with status 'done'
Successfully installed docopt-0.6.2 pygtfs-0.1.3 pytz-2017.2 six-1.11.0 sqlalchemy-1.1.14
Target directory C:\Users\Owner\PycharmProjects\PatcoSchedule\deployments\deployment_15\six-1.11.0.dist-info already exists. Specify --upgrade to force replacement.
Target directory C:\Users\Owner\PycharmProjects\PatcoSchedule\deployments\deployment_15\six.py already exists. Specify --upgrade to force replacement.
Target directory C:\Users\Owner\PycharmProjects\PatcoSchedule\deployments\deployment_15\__pycache__ already exists. Specify --upgrade to force replacement.

Process finished with exit code 0
C:\ProgramData\Anaconda3\python.exe C:/Users/Owner/PycharmProjects/PatcoSchedule/create_deployment.py
Collecting requests==2.8.1
  Using cached requests-2.8.1-py2.py3-none-any.whl
Installing collected packages: requests
Successfully installed requests-2.8.1
Collecting sseclient==0.0.11
Collecting requests>=2.0.0 (from sseclient==0.0.11)
  Using cached requests-2.18.4-py2.py3-none-any.whl
Collecting six (from sseclient==0.0.11)
  Using cached six-1.11.0-py2.py3-none-any.whl
Collecting chardet<3.1.0,>=3.0.2 (from requests>=2.0.0->sseclient==0.0.11)
  Using cached chardet-3.0.4-py2.py3-none-any.whl
Collecting urllib3<1.23,>=1.21.1 (from requests>=2.0.0->sseclient==0.0.11)
  Using cached urllib3-1.22-py2.py3-none-any.whl
Collecting certifi>=2017.4.17 (from requests>=2.0.0->sseclient==0.0.11)
  Using cached certifi-2017.7.27.1-py2.py3-none-any.whl
Collecting idna<2.7,>=2.5 (from requests>=2.0.0->sseclient==0.0.11)
  Using cached idna-2.6-py2.py3-none-any.whl
Installing collected packages: chardet, urllib3, certifi, idna, requests, six, sseclient
Successfully installed certifi-2017.7.27.1 chardet-3.0.4 idna-2.6 requests-2.18.4 six-1.11.0 sseclient-0.0.11 urllib3-1.22
Target directory C:\Users\Owner\PycharmProjects\PatcoSchedule\deployments\deployment_15\requests already exists. Specify --upgrade to force replacement.
Collecting hammock==0.2.4
Collecting requests>=1.1.0 (from hammock==0.2.4)
  Using cached requests-2.18.4-py2.py3-none-any.whl
Collecting idna<2.7,>=2.5 (from requests>=1.1.0->hammock==0.2.4)
  Using cached idna-2.6-py2.py3-none-any.whl
Collecting urllib3<1.23,>=1.21.1 (from requests>=1.1.0->hammock==0.2.4)
  Using cached urllib3-1.22-py2.py3-none-any.whl
Collecting certifi>=2017.4.17 (from requests>=1.1.0->hammock==0.2.4)
  Using cached certifi-2017.7.27.1-py2.py3-none-any.whl
Collecting chardet<3.1.0,>=3.0.2 (from requests>=1.1.0->hammock==0.2.4)
  Using cached chardet-3.0.4-py2.py3-none-any.whl
Installing collected packages: idna, urllib3, certifi, chardet, requests, hammock
Successfully installed certifi-2017.7.27.1 chardet-3.0.4 hammock-0.2.4 idna-2.6 requests-2.18.4 urllib3-1.22
Target directory C:\Users\Owner\PycharmProjects\PatcoSchedule\deployments\deployment_15\certifi already exists. Specify --upgrade to force replacement.
Target directory C:\Users\Owner\PycharmProjects\PatcoSchedule\deployments\deployment_15\certifi-2017.7.27.1.dist-info already exists. Specify --upgrade to force replacement.
Target directory C:\Users\Owner\PycharmProjects\PatcoSchedule\deployments\deployment_15\chardet already exists. Specify --upgrade to force replacement.
Target directory C:\Users\Owner\PycharmProjects\PatcoSchedule\deployments\deployment_15\chardet-3.0.4.dist-info already exists. Specify --upgrade to force replacement.
Target directory C:\Users\Owner\PycharmProjects\PatcoSchedule\deployments\deployment_15\idna already exists. Specify --upgrade to force replacement.
Target directory C:\Users\Owner\PycharmProjects\PatcoSchedule\deployments\deployment_15\idna-2.6.dist-info already exists. Specify --upgrade to force replacement.
Target directory C:\Users\Owner\PycharmProjects\PatcoSchedule\deployments\deployment_15\requests already exists. Specify --upgrade to force replacement.
Target directory C:\Users\Owner\PycharmProjects\PatcoSchedule\deployments\deployment_15\requests-2.18.4.dist-info already exists. Specify --upgrade to force replacement.
Target directory C:\Users\Owner\PycharmProjects\PatcoSchedule\deployments\deployment_15\urllib3 already exists. Specify --upgrade to force replacement.
Target directory C:\Users\Owner\PycharmProjects\PatcoSchedule\deployments\deployment_15\urllib3-1.22.dist-info already exists. Specify --upgrade to force replacement.
Target directory C:\Users\Owner\PycharmProjects\PatcoSchedule\deployments\deployment_15\__pycache__ already exists. Specify --upgrade to force replacement.
Collecting pygtfs==0.1.3
  Using cached pygtfs-0.1.3-py2.py3-none-any.whl
Collecting sqlalchemy>=0.7.8 (from pygtfs==0.1.3)
  Using cached SQLAlchemy-1.1.14.tar.gz
Collecting six (from pygtfs==0.1.3)
  Using cached six-1.11.0-py2.py3-none-any.whl
Collecting pytz>=2012d (from pygtfs==0.1.3)
  Using cached pytz-2017.2-py2.py3-none-any.whl
Collecting docopt (from pygtfs==0.1.3)
Installing collected packages: sqlalchemy, six, pytz, docopt, pygtfs
  Running setup.py install for sqlalchemy: started
    Running setup.py install for sqlalchemy: finished with status 'done'
Successfully installed docopt-0.6.2 pygtfs-0.1.3 pytz-2017.2 six-1.11.0 sqlalchemy-1.1.14
Target directory C:\Users\Owner\PycharmProjects\PatcoSchedule\deployments\deployment_15\six-1.11.0.dist-info already exists. Specify --upgrade to force replacement.
Target directory C:\Users\Owner\PycharmProjects\PatcoSchedule\deployments\deployment_15\six.py already exists. Specify --upgrade to force replacement.
Target directory C:\Users\Owner\PycharmProjects\PatcoSchedule\deployments\deployment_15\__pycache__ already exists. Specify --upgrade to force replacement.

进程以退出代码 0 结束

这里是create_deployment文件,代码是从https://github.com/youngsoul/AlexaDeploymentSample复制过来的

import os
import subprocess
import zipfile


"""
Script will create an AWS Lambda function deployment.

It expects there to be a deployments directory and it will create a
deployment of the form:

deployment_n

where n is incremented for each deployment based on the existing deployment
directories

"""

root_deployments_dir = "./deployments"

# List of files that should be included in the deployment
# Only the files listed here, and the libraries in the requirements.txt
# file will be included in the deployment.
deployment_files = ['AlexaBaseHandler.py', 'AlexaDeploymentHandler.py', 'main.py']

def _read_requirements():
    with open("./requirements.txt", 'r') as f:
        install_requirements = f.readlines()

    return install_requirements

def _get_immediate_subdirectories(a_dir):
    return [name for name in os.listdir(a_dir)
            if os.path.isdir(os.path.join(a_dir, name))]

def _make_deployment_dir():
    all_deployment_directories = _get_immediate_subdirectories(root_deployments_dir)
    max_deployment_number = -1
    for deployment_dir in all_deployment_directories:
        dir_name_elements = deployment_dir.split("_")
        if( len(dir_name_elements) == 2):
            if int(dir_name_elements[1]) > max_deployment_number:
                max_deployment_number = int(dir_name_elements[1])

    if max_deployment_number == -1:
        max_deployment_number = 0

    deployment_name = "deployment_{0}".format(max_deployment_number+1)
    new_deployment_dir_path = "{0}/{1}".format(root_deployments_dir, deployment_name)

    if not os.path.exists(new_deployment_dir_path):
        os.mkdir(new_deployment_dir_path)

    return (new_deployment_dir_path, deployment_name)

def _install_requirements(deployment_requirements, deployment_dir):
    """
    pip install <requirements line> -t <deployment_dir>
    :param deployment_requirements
    :param deployment_dir:
    :return:
    """
    if os.path.exists(deployment_dir):
        for requirement in deployment_requirements:
            cmd = "pip install {0} -t {1}".format(requirement, deployment_dir).split()
            return_code = subprocess.call(cmd, shell=False)

def _copy_deployment_files(deployment_dir):
    for deployment_file in deployment_files:
        if os.path.exists(deployment_file):
            cmd = "{0} {1}".format(deployment_file, deployment_dir).split()
            return_code = subprocess.call(cmd, shell=False)
        else:
            raise NameError("Deployment file not found [{0}]".format(deployment_file))


def zipdir(dirPath=None, zipFilePath=None, includeDirInZip=False):
    """
    Attribution:  I wish I could remember where I found this on the
    web.  To the unknown sharer of knowledge - thank you.

    Create a zip archive from a directory.

    Note that this function is designed to put files in the zip archive with
    either no parent directory or just one parent directory, so it will trim any
    leading directories in the filesystem paths and not include them inside the
    zip archive paths. This is generally the case when you want to just take a
    directory and make it into a zip file that can be extracted in different
    locations.

    Keyword arguments:

    dirPath -- string path to the directory to archive. This is the only
    required argument. It can be absolute or relative, but only one or zero
    leading directories will be included in the zip archive.

    zipFilePath -- string path to the output zip file. This can be an absolute
    or relative path. If the zip file already exists, it will be updated. If
    not, it will be created. If you want to replace it from scratch, delete it
    prior to calling this function. (default is computed as dirPath + ".zip")

    includeDirInZip -- boolean indicating whether the top level directory should
    be included in the archive or omitted. (default True)

"""
    if not zipFilePath:
        zipFilePath = dirPath + ".zip"
    if not os.path.isdir(dirPath):
        raise OSError("dirPath argument must point to a directory. "
            "'%s' does not." % dirPath)
    parentDir, dirToZip = os.path.split(dirPath)
    #Little nested function to prepare the proper archive path
    def trimPath(path):
        archivePath = path.replace(parentDir, "", 1)
        if parentDir:
            archivePath = archivePath.replace(os.path.sep, "", 1)
        if not includeDirInZip:
            archivePath = archivePath.replace(dirToZip + os.path.sep, "", 1)
        return os.path.normcase(archivePath)

    outFile = zipfile.ZipFile(zipFilePath, "w",
        compression=zipfile.ZIP_DEFLATED)
    for (archiveDirPath, dirNames, fileNames) in os.walk(dirPath):
        for fileName in fileNames:
            filePath = os.path.join(archiveDirPath, fileName)
            outFile.write(filePath, trimPath(filePath))
        #Make sure we get empty directories as well
        if not fileNames and not dirNames:
            #or
            #zipInfo.external_attr = 48
            #Here to allow for inserting an empty directory.  Still TBD/TODO.
            outFile.writestr(zipInfo, "")
    outFile.close()

if __name__ == "__main__":
    (deployment_dir, deployment_name) = _make_deployment_dir()
    _copy_deployment_files(deployment_dir)
    install_requirements = _read_requirements()
    _install_requirements(install_requirements, deployment_dir)

    zipdir(deployment_dir, "{0}/{1}.zip".format(root_deployments_dir, deployment_name))

更新

NVM 我想通了。我复制的代码使用 cp 作为子进程的复制命令。我查找了我的操作系统(Windows 10)的命令,它是 COPY 而不是 cp。这是对子进程的新调用

cmd = "COPY {0}
    {1}".format(deployment_file,os.path.abspath(deployment_dir)).split()

【问题讨论】:

  • NVM 我想通了。我复制的代码使用 cp 作为子进程的复制命令。我查找了我的操作系统(Windows 10)的命令,它是 COPY 而不是 cp。这是对子进程的新调用 cmd = "COPY {0} {1}".format(deployment_file, os.path.abspath(deployment_dir)).split()
  • 您应该将其添加为答案,并将其标记为已接受

标签: python amazon-web-services deployment aws-lambda


【解决方案1】:

NVM 我想通了。我复制的代码使用 cp 作为子进程的复制命令。我查找了我的操作系统(Windows 10)的命令,它是 COPY 而不是 cp。这是对子进程的新调用 cmd = "COPY {0} {1}".format(deployment_file, os.path.abspath(deployment_dir)).split()

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-03-05
    • 1970-01-01
    • 2020-08-01
    • 2021-10-05
    • 2022-11-04
    • 2019-12-08
    • 2022-01-21
    • 1970-01-01
    相关资源
    最近更新 更多