Python AWS Lambda“;errorMessage";:&引用;[Errno 26]文本文件正忙”;

Python AWS Lambda“;errorMessage";:&引用;[Errno 26]文本文件正忙”;,python,amazon-web-services,selenium-webdriver,aws-lambda,aws-sam-cli,Python,Amazon Web Services,Selenium Webdriver,Aws Lambda,Aws Sam Cli,我编写了代码,并通过AWS SAM CLI成功地将其上传到AWS Lambda。它基本上进入我提供的URL,并打印网站的标题。一个非常初级的代码。下面是我的代码: import os, shutil, uuid, time from selenium import webdriver def setup(): BIN_DIR = "/tmp/bin" if not os.path.exists(BIN_DIR): print("Cr

我编写了代码,并通过AWS SAM CLI成功地将其上传到AWS Lambda。它基本上进入我提供的URL,并打印网站的标题。一个非常初级的代码。下面是我的代码:

import os, shutil, uuid, time
from selenium import webdriver

def setup():
    BIN_DIR = "/tmp/bin"
    if not os.path.exists(BIN_DIR):
        print("Creating bin folder")
        os.makedirs(BIN_DIR)

    LIB_DIR = '/tmp/bin/lib'
    if not os.path.exists(LIB_DIR):
        print("Creating lib folder")
        os.makedirs(LIB_DIR)
        
    for filename in ['chromedriver', 'headless-chromium', 'lib/libgconf-2.so.4', 'lib/libORBit-2.so.0']:
        oldfile = f'/opt/{filename}'
        newfile = f'{BIN_DIR}/{filename}'
        shutil.copy2(oldfile, newfile)
        os.chmod(newfile, 0o775)

def init_web_driver():
    setup()
    chrome_options = webdriver.ChromeOptions()
    _tmp_folder = '/tmp/{}'.format(uuid.uuid4())

    if not os.path.exists(_tmp_folder):
        os.makedirs(_tmp_folder)

    if not os.path.exists(_tmp_folder + '/user-data'):
        os.makedirs(_tmp_folder + '/user-data')

    if not os.path.exists(_tmp_folder + '/data-path'):
        os.makedirs(_tmp_folder + '/data-path')

    if not os.path.exists(_tmp_folder + '/cache-dir'):
        os.makedirs(_tmp_folder + '/cache-dir')

    chrome_options.add_argument('--headless')
    chrome_options.add_argument('--no-sandbox')
    chrome_options.add_argument('--disable-gpu')
    chrome_options.add_argument('--window-size=1280x1696')
    chrome_options.add_argument('--user-data-dir={}'.format(_tmp_folder + '/user-data'))
    chrome_options.add_argument('--hide-scrollbars')
    chrome_options.add_argument('--enable-logging')
    chrome_options.add_argument('--log-level=0')
    chrome_options.add_argument('--v=99')
    chrome_options.add_argument('--single-process')
    chrome_options.add_argument('--data-path={}'.format(_tmp_folder + '/data-path'))
    chrome_options.add_argument('--ignore-certificate-errors')
    chrome_options.add_argument('--homedir={}'.format(_tmp_folder))
    chrome_options.add_argument('--disk-cache-dir={}'.format(_tmp_folder + '/cache-dir'))
    chrome_options.add_argument(
        'user-agent=Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/61.0.3163.100 Safari/537.36')

    chrome_options.binary_location = "/tmp/bin/headless-chromium"

    driver = webdriver.Chrome(chrome_options=chrome_options)
    return driver

def lambda_handler(event, context):
    driver = init_web_driver()
    driver.get("http://www.mjlivesey.co.uk")
    time.sleep(4)
    print(driver.title)
当我第一次单击“测试”按钮时,我可以在输出屏幕中看到“driver.title”。但当我在几秒钟后再次单击时,会显示以下错误:

{
  "errorMessage": "[Errno 26] Text file busy: '/tmp/bin/chromedriver'",
  "errorType": "OSError",
  "stackTrace": [
    "  File \"/var/task/app.py\", line 61, in lambda_handler\n    driver = init_web_driver()\n",
    "  File \"/var/task/app.py\", line 22, in init_web_driver\n    setup()\n",
    "  File \"/var/task/app.py\", line 18, in setup\n    shutil.copy2(oldfile, newfile)\n",
    "  File \"/var/lang/lib/python3.7/shutil.py\", line 266, in copy2\n    copyfile(src, dst, follow_symlinks=follow_symlinks)\n",
    "  File \"/var/lang/lib/python3.7/shutil.py\", line 121, in copyfile\n    with open(dst, 'wb') as fdst:\n"
  ]
}
如果我等待半小时或更长时间,我可以再次成功运行代码。我不明白这里的问题。也许你们能帮我明白这一点


谢谢。

似乎对同一函数的多次调用都涉及到相同的文件,在这些文件上以前的执行仍然具有活动锁定

要了解这种行为,了解实际工作原理是很有用的。基本上,如果您在短时间内多次执行相同的功能,AWS将尝试重用相同的执行环境和资源;这节省了时间和资源

只是为了实现并行,所发生的事情与在本地并行执行代码几次是一样的。由于所有进程都在相同的文件/文件夹上读写,因此将不可避免地出现争用情况

在您的情况下,您应该重构
设置
函数,使其内容在每个执行环境中只执行一次


另外,您应该注意
/tmp
目录的硬限制为512MB,超过此限制,您的函数将被终止。如果你想坚持你的数据和/或有更多的净空,你应该考虑进去。

< P>只是添加到前一个答案,我使用相同的代码,我发现这是为了删除TMP文件夹,并使后续的LAMBDAS运行。
def setup():
    BIN_DIR = "/tmp/bin"
    if not os.path.exists(BIN_DIR):
        print("Creating bin folder")
        os.makedirs(BIN_DIR)
    else:
        print("Delete all files in folder")
        for filename in os.listdir(BIN_DIR):
            file_path = os.path.join(BIN_DIR, filename)
            try:
                if os.path.isfile(file_path) or os.path.islink(file_path):
                    os.unlink(file_path)
                elif os.path.isdir(file_path):
                    shutil.rmtree(file_path)
            except Exception as e:
                print('Failed to delete %s. Reason: %s' % (file_path, e))
        print("Deleting bin folder")
        os.rmdir(BIN_DIR)
        print("Creating bin folder")
        os.makedirs(BIN_DIR)

谢谢你的解释。