【问题标题】:Python script on ubuntu - OSError: [Errno 12] Cannot allocate memoryubuntu 上的 Python 脚本 - OSError: [Errno 12] 无法分配内存
【发布时间】:2020-03-07 15:41:07
【问题描述】:

我正在 AWS (Ubunut) EC2 实例上运行脚本。这是一个使用 selenium/chromedriver 和 headless chrome 来抓取一些网页的网络爬虫。我之前运行过这个脚本没有问题,但今天我遇到了一个错误。这是脚本:

options = Options()
options.add_argument('--no-sandbox')
options.add_argument('--window-size=1420,1080')
options.add_argument('--headless')
options.add_argument('--disable-dev-shm-usage')
options.add_argument('--disable-gpu')
options.add_argument("--disable-notifications")

options.binary_location='/usr/bin/chromium-browser'
driver = webdriver.Chrome(chrome_options=options)


#Set base url (SAN FRANCISCO)
base_url = 'https://www.bandsintown.com/en/c/san-francisco-ca?page='

events = []

for i in range(1,90):
    #cycle through pages in range
    driver.get(base_url + str(i))
    pageURL = base_url + str(i)
    print(pageURL)

当我从 ubuntu 运行这个脚本时,我得到这个错误:

  Traceback (most recent call last):
  File "BandsInTown_Scraper_SF.py", line 91, in <module>
    driver = webdriver.Chrome(chrome_options=options)
  File "/home/ubuntu/.local/lib/python3.6/site-packages/selenium/webdriver/chrome/webdriver.py", line 73, in __init__
    self.service.start()
  File "/home/ubuntu/.local/lib/python3.6/site-packages/selenium/webdriver/common/service.py", line 76, in start
    stdin=PIPE)
  File "/usr/lib/python3.6/subprocess.py", line 729, in __init__
    restore_signals, start_new_session)
  File "/usr/lib/python3.6/subprocess.py", line 1295, in _execute_child
    restore_signals, start_new_session, preexec_fn)
OSError: [Errno 12] Cannot allocate memory

我确认我正在运行相同版本的 Chromedriver/Chromium 浏览器:

ChromeDriver 79.0.3945.130 (e22de67c28798d98833a7137c0e22876237fc40a-refs/branch-heads/3945@{#1047})


Chromium 79.0.3945.130 Built on Ubuntu , running on Ubuntu 18.04

对于它的价值,我在 Mac 上运行了这个,并且我确实有多个像这个一样的网络抓取脚本在同一个 EC2 实例上运行(到目前为止只有 2 个脚本,所以不多)。

更新

我现在尝试在 ubuntu 上运行此脚本时也遇到这些错误:

    Traceback (most recent call last):
      File "/usr/lib/python3/dist-packages/urllib3/connection.py", line 141, in _new_conn
        (self.host, self.port), self.timeout, **extra_kw)
      File "/usr/lib/python3/dist-packages/urllib3/util/connection.py", line 60, in create_connection
        for res in socket.getaddrinfo(host, port, family, socket.SOCK_STREAM):
      File "/usr/lib/python3.6/socket.py", line 745, in getaddrinfo
        for res in _socket.getaddrinfo(host, port, family, type, proto, flags):
    socket.gaierror: [Errno -3] Temporary failure in name resolution


     During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/usr/lib/python3/dist-packages/urllib3/connectionpool.py", line 601, in urlopen
    chunked=chunked)
  File "/usr/lib/python3/dist-packages/urllib3/connectionpool.py", line 346, in _make_request
    self._validate_conn(conn)
  File "/usr/lib/python3/dist-packages/urllib3/connectionpool.py", line 852, in _validate_conn
    conn.connect()
  File "/usr/lib/python3/dist-packages/urllib3/connection.py", line 284, in connect
    conn = self._new_conn()
  File "/usr/lib/python3/dist-packages/urllib3/connection.py", line 150, in _new_conn
    self, "Failed to establish a new connection: %s" % e)
urllib3.exceptions.NewConnectionError: <urllib3.connection.VerifiedHTTPSConnection object at 0x7f90945757f0>: Failed to establish a new connection: [Errno -3] Temporary failure in name resolution

    During handling of the above exception, another exception occurred:

    Traceback (most recent call last):
      File "/home/ubuntu/.local/lib/python3.6/site-packages/requests/adapters.py", line 449, in send
        timeout=timeout
    ^[[B  File "/usr/lib/python3/dist-packages/urllib3/connectionpool.py", line 639, in urlopen
    ^[[B^[[A^[[A    _stacktrace=sys.exc_info()[2])
      File "/usr/lib/python3/dist-packages/urllib3/util/retry.py", line 398, in increment
        raise MaxRetryError(_pool, url, error or ResponseError(cause))
    urllib3.exceptions.MaxRetryError: HTTPSConnectionPool(host='www.bandsintown.com', port=443): Max retries exceeded with url: /en/c/san-francisco-ca?page=6 (Caused by NewConnectionError('<urllib3.connection.VerifiedHTTPSConnection object at 0x7f90945757f0>: Failed to establish a new connection: [Errno -3] Temporary failure in name resolution',))

    During handling of the above exception, another exception occurred:

    Traceback (most recent call last):
      File "BandsInTown_Scraper_SF.py", line 39, in <module>
        res = requests.get(url)
      File "/home/ubuntu/.local/lib/python3.6/site-packages/requests/api.py", line 75, in get
        return request('get', url, params=params, **kwargs)
      File "/home/ubuntu/.local/lib/python3.6/site-packages/requests/api.py", line 60, in request
        return session.request(method=method, url=url, **kwargs)
      File "/home/ubuntu/.local/lib/python3.6/site-packages/requests/sessions.py", line 533, in request
        resp = self.send(prep, **send_kwargs)
      File "/home/ubuntu/.local/lib/python3.6/site-packages/requests/sessions.py", line 646, in send
        r = adapter.send(request, **kwargs)
      File "/home/ubuntu/.local/lib/python3.6/site-packages/requests/adapters.py", line 516, in send
        raise ConnectionError(e, request=request)
    requests.exceptions.ConnectionError: HTTPSConnectionPool(host='www.bandsintown.com', port=443): Max retries exceeded with url: /en/c/san-francisco-ca?page=6 (Caused by NewConnectionError('<urllib3.connection.VerifiedHTTPSConnection object at 0x7f90945757f0>: Failed to establish a new connection: [Errno -3] Temporary failure in name resolution',))

最后,这是我目前每月的 AWS 使用情况,它没有显示超出任何内存配额。

【问题讨论】:

    标签: python-3.x selenium amazon-ec2 selenium-chromedriver ubuntu-14.04


    【解决方案1】:

    此错误消息...

        restore_signals, start_new_session, preexec_fn)
    OSError: [Errno 12] Cannot allocate memory
    

    ...暗示操作系统无法分配内存来启动/产生一个新会话

    另外,这个错误信息...

    urllib3.exceptions.MaxRetryError: HTTPSConnectionPool(host='www.bandsintown.com', port=443): Max retries exceeded with url: /en/c/san-francisco-ca?page=6 (Caused by NewConnectionError('<urllib3.connection.VerifiedHTTPSConnection object at 0x7f90945757f0>: Failed to establish a new connection: [Errno -3] Temporary failure in name resolution',))
    

    ...表示您的程序已成功迭代到 第 5 页,而在 第 6 页,您会看到此错误。


    我在您的代码块中没有看到任何问题。我取了你的代码,做了一些小的调整,下面是执行结果:

    • 代码块:

      options = webdriver.ChromeOptions() 
      options.add_argument("start-maximized")
      options.add_experimental_option("excludeSwitches", ["enable-automation"])
      options.add_experimental_option('useAutomationExtension', False)
      driver = webdriver.Chrome(options=options, executable_path=r'C:\WebDrivers\chromedriver.exe')
      base_url = 'https://www.bandsintown.com/en/c/san-francisco-ca?page='
      for i in range(1,10):
          #cycle through pages in range
          driver.get(base_url + str(i))
          pageURL = base_url + str(i)
          print(pageURL)
      
    • 控制台输出:

      https://www.bandsintown.com/en/c/san-francisco-ca?page=1
      https://www.bandsintown.com/en/c/san-francisco-ca?page=2
      https://www.bandsintown.com/en/c/san-francisco-ca?page=3
      https://www.bandsintown.com/en/c/san-francisco-ca?page=4
      https://www.bandsintown.com/en/c/san-francisco-ca?page=5
      https://www.bandsintown.com/en/c/san-francisco-ca?page=6
      https://www.bandsintown.com/en/c/san-francisco-ca?page=7
      https://www.bandsintown.com/en/c/san-francisco-ca?page=8
      https://www.bandsintown.com/en/c/san-francisco-ca?page=9
      

    深潜

    这个错误来自subprocess.py:

    self.pid = _posixsubprocess.fork_exec(
        args, executable_list,
        close_fds, tuple(sorted(map(int, fds_to_keep))),
        cwd, env_list,
        p2cread, p2cwrite, c2pread, c2pwrite,
        errread, errwrite,
        errpipe_read, errpipe_write,
        restore_signals, start_new_session, preexec_fn)
    

    但是,根据 OSError: [Errno 12] Cannot allocate memory 中的讨论,此错误 OSError: [Errno 12] Cannot allocate memoryRAM / SWAP 有关。


    交换空间

    Swap Space 是系统硬盘驱动器中的内存空间,已被指定为 临时存储其无法在 RAM 中保存的数据的位置。这使您能够增加程序可以在其工作 中保留的数据量。硬盘驱动器上的交换空间将主要用于当 RAM 中不再有足够的空间来保存正在使用的应用程序数据时。但是,写入 I/O 的信息将比保存在 RAM 中的信息慢得多,但操作系统更愿意将运行的应用程序数据保留在内存中,并为较旧的数据使用交换空间。部署交换空间作为系统 RAM 耗尽时的后备是针对具有可用非 SSD 存储的系统上的out-of-memory 问题的安全措施。


    系统检查

    要检查系统是否已经有一些可用的交换空间,您需要执行以下命令:

    $ sudo swapon --show
    

    如果您没有得到任何输出,这意味着您的系统当前没有可用的交换空间。您还可以使用免费实用程序验证是否没有活动交换,如下所示:

    $ free -h
    

    如果系统中没有活动交换,您将看到如下输出:

    Output
                   total        used       free        shared      buff/cache  available
    Mem:           488M         36M        104M        652K        348M        426M
    Swap:            0B          0B          0B
    

    创建交换文件

    在这些情况下,您需要为交换分配空间以用作专用于该任务的单独分区,并且您可以创建驻留在现有分区上的交换文件。要创建一个 1 GB 的文件,您需要执行以下命令:

    $ sudo fallocate -l 1G /swapfile
    

    您可以通过执行以下命令来验证是否保留了正确的空间量:

    $ ls -lh /swapfile
    
    #Output
    $ -rw-r--r-- 1 root root 1.0G Mar 08 10:30 /swapfile
    

    这确认 交换文件 已创建并预留了正确的空间量。


    启用交换空间

    一旦有正确大小的文件可用,我们就需要将其实际转换为交换空间。现在您需要锁定文件的权限,以便只有具有特定权限的用户才能读取内容。这可以防止非预期用户能够访问该文件,这将产生重大的安全隐患。因此,您需要按照以下步骤操作:

    • 使文件只能由特定用户访问,例如root 通过执行以下命令:

      $ sudo chmod 600 /swapfile
      
    • 通过执行以下命令验证权限更改:

      $ ls -lh /swapfile
      
      #Output
      -rw------- 1 root root 1.0G Apr 25 11:14 /swapfile
      

      这确认只有 root 用户启用了读写标志。

    • 现在您需要通过执行以下命令将文件标记为交换空间:

      $ sudo mkswap /swapfile
      
      #Sample Output
      Setting up swapspace version 1, size = 1024 MiB (1073737728 bytes)
      no label, UUID=6e965805-2ab9-450f-aed6-577e74089dbf
      
    • 接下来您需要启用交换文件,允许系统开始使用它执行以下命令:

      $ sudo swapon /swapfile
      
    • 您可以通过执行以下命令来验证交换是否可用:

      $ sudo swapon --show
      
      #Sample Output
      NAME      TYPE  SIZE USED PRIO
      /swapfile file 1024M   0B   -1
      
    • 最后通过执行以下命令再次检查free 实用程序的输出以验证设置:

      $ free -h
      
      #Sample Output
                total        used        free      shared  buff/cache   available
      Mem:           488M         37M         96M        652K        354M        425M
      Swap:          1.0G          0B        1.0G
      

    结论

    一旦 Swap Space 设置成功,底层操作系统将根据需要开始使用它。

    【讨论】:

    • 这个主意不错,加入swap绝对值得一试
    • @Vorsprung 添加交换空间应该可以解决 OP。
    • 谢谢!我听从了你的建议,当我使用命令“udo swapon --show”时,确实没有看到任何内存。所以,我做了 '$ sudo fallocate -l 1G /swapfile' 。我仍然遇到同样的错误,并且运行“$ free -h”,我仍然看不到任何交换空间。
    • 我假设一旦我添加了交换空间,它应该在我执行“free -h”命令时显示?
    • 我通常会使用 mount 或 swapon 来激活交换文件,试试swapon /swapfile
    【解决方案2】:

    可能发生的事情是 Chromium 浏览器已更新,现在占用了更多内存(或者可能内存泄漏更严重......你没有说它在死前获得了多少个 url)

    作为一种变通方法,启动更大的实例大小。不要说您使用的实例大小,但如果您有 t3.micro,请尝试使用 t3.medium。

    这里有一个易于理解的图表https://www.ec2instances.info/?region=eu-west-1

    如果您已经启动了一个实例并且想要调整它的大小而不从头开始重建,那么使用控制台将其设置为已停止状态,更改大小并重新开始

    【讨论】:

    • 谢谢 Vorsprung。为什么铬浏览器会自动更新?我没有做任何更改。
    • 另外:我正在使用 AWS 的免费版本,即 t2.Micro,它有 1.0 GiB。我看到 t3 Medium 有 4.0 GiB,但对于 Linux 按需成本来说,每小时的成本是 0.045 美分。这大约是每月 35 美元。如果我让我的实例每天 24 小时运行。有没有办法预测什么?我的费用可能是?谢谢。
    • 某些 Linux 安装会自动更新,因此可能会在未经您同意的情况下进行更新...我当然无法确定!无论系统内存不足的原因是什么,增加实例大小是解决问题的简单方法。查看计算器有用的成本calculator.s3.amazonaws.com/index.html
    • 脚本运行时超出的内存大小是ec2上的RAM。这在 1GB 的 t2.micro 上是固定的。计费信息仅包含这么多小时的 ec2 - 以固定的内存大小。
    • 按照本页 docs.aws.amazon.com/AWSEC2/latest/UserGuide/… 上“调整 Amazon EBS 支持的实例的大小”下的指南进行操作
    猜你喜欢
    • 2010-11-24
    • 2013-08-01
    • 2015-05-04
    • 1970-01-01
    • 2017-07-23
    • 1970-01-01
    • 1970-01-01
    • 2010-11-16
    • 1970-01-01
    相关资源
    最近更新 更多