Python 线程处理 - 内部缓冲区错误 - 内存不足
Python threading - internal buffer error - out of memory
我制作了一个简单的网络爬虫,使用 urllib 和 beautifulsoup 从网页上的 table 提取数据。为了加快数据拉取速度,我尝试使用线程,但出现以下错误:
"internal buffer error : memory allocation failed : growing buffer"
此消息出现了很多次,然后指出:
"out of memory"
感谢您的帮助。
from bs4 import BeautifulSoup
from datetime import datetime
import urllib2
import re
from threading import Thread
stockData = []
#Access the list of stocks to search for data
symbolfile = open("stocks.txt")
symbolslist = symbolfile.read()
newsymbolslist = symbolslist.split("\n")
#text file stock data is stored in
myfile = open("webcrawldata.txt","a")
#initializing data for extraction of web data
lineOfData = ""
i=0
def th(ur):
stockData = []
lineOfData = ""
dataline = ""
stats = ""
page = ""
soup = ""
i=0
#creates a timestamp for when program was won
timestamp = datetime.now()
#Get Data ONLINE
#bloomberg stock quotes
url= "http://www.bloomberg.com/quote/" + ur + ":US"
page = urllib2.urlopen(url)
soup = BeautifulSoup(page.read())
#Extract key stats table only
stats = soup.find("table", {"class": "key_stat_data" })
#iteration for <tr>
j = 0
try:
for row in stats.findAll('tr'):
stockData.append(row.find('td'))
j += 1
except AttributeError:
print "Table handling error in HTML"
k=0
for cell in stockData:
#clean up text
dataline = stockData[k]
lineOfData = lineOfData + " " + str(dataline)
k += 1
g = str(timestamp) + " " + str(ur)+ ' ' + str(lineOfData) + ' ' + ("\n\n\n")
myfile.write(g)
print (ur + "\n")
del stockData[:]
lineOfData = ""
dataline = ""
stats = None
page = None
soup = None
i += 1
threadlist = []
for u in newsymbolslist:
t = Thread(target = th, args = (u,))
t.start()
threadlist.append(t)
for b in threadlist:
b.join()enter code here
不要重新发明轮子,用Scrapy
web-scraping framework:
Scrapy is an application framework for crawling web sites and
extracting structured data which can be used for a wide range of
useful applications, like data mining, information processing or
historical archival.
想一想 - scalability/parallelizing/performance 问题已 为你解决 - 你真的想继续潜入 Thread
的精彩世界吗 python,让你的代码有异味,达到 CPU 和内存限制,处理冲突,最后,让你的代码无法调试和维护——而不是专注于提取和收集数据?而且,即使 gevent
我怀疑你的最终代码是否会像你基于 Scrapy 实现的那样更简单和可读。为什么不使用经过大量用户测试和使用的工具,该工具被证明是网络抓取 python 世界中有史以来最好的工具?
这里有一个 working 蜘蛛,它以类似的方式抓取引号:
from scrapy.spider import Spider
from scrapy.item import Item, Field
from scrapy.http import Request
class BloombergItem(Item):
ur = Field()
parameter = Field()
value = Field()
class BloombergSpider(Spider):
name = 'bloomberg'
allowed_domains = ['www.bloomberg.com']
def start_requests(self):
with open("stocks.txt") as f:
for ur in f:
yield Request("http://www.bloomberg.com/quote/%s:US" % ur)
def parse(self, response):
for parameter in response.css('table.key_stat_data tr'):
item = BloombergItem()
item['ur'] = response.xpath('//title/text()').extract()[0].split(':')[0]
item['parameter'] = parameter.xpath('th/text()').extract()[0]
item['value'] = parameter.xpath('td/text()').extract()[0]
yield item
如果stocks.txt
的内容是:
AAPL
爬虫会输出(比如你选择JSON输出):
[
{
"parameter": "Current P/E Ratio (ttm)",
"value": "16.6091",
"ur": "AAPL"
},
{
"parameter": "Estimated P/E(09/2015)",
"value": "13.6668",
"ur": "AAPL"
},
{
"parameter": "Relative P/E vs.",
"value": "0.9439",
"ur": "AAPL"
},
...
]
开始使用 Scrapy 的一个好地方是 Scrapy Tutorial.
您启动的每个线程都有一个线程堆栈大小,即 8 kb
Linux 系统中的默认值(参见 ulimit -s
),因此您的线程所需的内存总数将超过 20 GB。
您可以使用线程池,例如 10 个线程;当一个
完成了它的工作,它有另一个任务要做。
但是:运行 线程多于 CPU 内核通常是胡说八道。所以我的
建议是停止使用线程。您可以使用 gevent 之类的库来
在不使用 OS 级线程的情况下做完全相同的事情。
gevent 的好处是猴子修补:你可以告诉 gevent
改变 Python 标准库的行为,这将改变你的
透明地进入 "greenlet" 个对象(参见 gevent 文档
更多细节)。 gevent提出的并发类型是
特别适合密集训练 I/O 就像你在做的那样。
在您的代码中,只需在开头添加以下内容:
from gevent import monkey; monkey.patch_all()
您不能同时打开超过 1024 个文件描述符
Linux 系统默认(参见 ulimit -n
)所以你必须增加
如果您希望同时打开 2700 个文件描述符,则此限制。
我制作了一个简单的网络爬虫,使用 urllib 和 beautifulsoup 从网页上的 table 提取数据。为了加快数据拉取速度,我尝试使用线程,但出现以下错误: "internal buffer error : memory allocation failed : growing buffer" 此消息出现了很多次,然后指出: "out of memory"
感谢您的帮助。
from bs4 import BeautifulSoup
from datetime import datetime
import urllib2
import re
from threading import Thread
stockData = []
#Access the list of stocks to search for data
symbolfile = open("stocks.txt")
symbolslist = symbolfile.read()
newsymbolslist = symbolslist.split("\n")
#text file stock data is stored in
myfile = open("webcrawldata.txt","a")
#initializing data for extraction of web data
lineOfData = ""
i=0
def th(ur):
stockData = []
lineOfData = ""
dataline = ""
stats = ""
page = ""
soup = ""
i=0
#creates a timestamp for when program was won
timestamp = datetime.now()
#Get Data ONLINE
#bloomberg stock quotes
url= "http://www.bloomberg.com/quote/" + ur + ":US"
page = urllib2.urlopen(url)
soup = BeautifulSoup(page.read())
#Extract key stats table only
stats = soup.find("table", {"class": "key_stat_data" })
#iteration for <tr>
j = 0
try:
for row in stats.findAll('tr'):
stockData.append(row.find('td'))
j += 1
except AttributeError:
print "Table handling error in HTML"
k=0
for cell in stockData:
#clean up text
dataline = stockData[k]
lineOfData = lineOfData + " " + str(dataline)
k += 1
g = str(timestamp) + " " + str(ur)+ ' ' + str(lineOfData) + ' ' + ("\n\n\n")
myfile.write(g)
print (ur + "\n")
del stockData[:]
lineOfData = ""
dataline = ""
stats = None
page = None
soup = None
i += 1
threadlist = []
for u in newsymbolslist:
t = Thread(target = th, args = (u,))
t.start()
threadlist.append(t)
for b in threadlist:
b.join()enter code here
不要重新发明轮子,用Scrapy
web-scraping framework:
Scrapy is an application framework for crawling web sites and extracting structured data which can be used for a wide range of useful applications, like data mining, information processing or historical archival.
想一想 - scalability/parallelizing/performance 问题已 为你解决 - 你真的想继续潜入 Thread
的精彩世界吗 python,让你的代码有异味,达到 CPU 和内存限制,处理冲突,最后,让你的代码无法调试和维护——而不是专注于提取和收集数据?而且,即使 gevent
我怀疑你的最终代码是否会像你基于 Scrapy 实现的那样更简单和可读。为什么不使用经过大量用户测试和使用的工具,该工具被证明是网络抓取 python 世界中有史以来最好的工具?
这里有一个 working 蜘蛛,它以类似的方式抓取引号:
from scrapy.spider import Spider
from scrapy.item import Item, Field
from scrapy.http import Request
class BloombergItem(Item):
ur = Field()
parameter = Field()
value = Field()
class BloombergSpider(Spider):
name = 'bloomberg'
allowed_domains = ['www.bloomberg.com']
def start_requests(self):
with open("stocks.txt") as f:
for ur in f:
yield Request("http://www.bloomberg.com/quote/%s:US" % ur)
def parse(self, response):
for parameter in response.css('table.key_stat_data tr'):
item = BloombergItem()
item['ur'] = response.xpath('//title/text()').extract()[0].split(':')[0]
item['parameter'] = parameter.xpath('th/text()').extract()[0]
item['value'] = parameter.xpath('td/text()').extract()[0]
yield item
如果stocks.txt
的内容是:
AAPL
爬虫会输出(比如你选择JSON输出):
[
{
"parameter": "Current P/E Ratio (ttm)",
"value": "16.6091",
"ur": "AAPL"
},
{
"parameter": "Estimated P/E(09/2015)",
"value": "13.6668",
"ur": "AAPL"
},
{
"parameter": "Relative P/E vs.",
"value": "0.9439",
"ur": "AAPL"
},
...
]
开始使用 Scrapy 的一个好地方是 Scrapy Tutorial.
您启动的每个线程都有一个线程堆栈大小,即 8 kb
Linux 系统中的默认值(参见 ulimit -s
),因此您的线程所需的内存总数将超过 20 GB。
您可以使用线程池,例如 10 个线程;当一个 完成了它的工作,它有另一个任务要做。
但是:运行 线程多于 CPU 内核通常是胡说八道。所以我的 建议是停止使用线程。您可以使用 gevent 之类的库来 在不使用 OS 级线程的情况下做完全相同的事情。
gevent 的好处是猴子修补:你可以告诉 gevent 改变 Python 标准库的行为,这将改变你的 透明地进入 "greenlet" 个对象(参见 gevent 文档 更多细节)。 gevent提出的并发类型是 特别适合密集训练 I/O 就像你在做的那样。
在您的代码中,只需在开头添加以下内容:
from gevent import monkey; monkey.patch_all()
您不能同时打开超过 1024 个文件描述符
Linux 系统默认(参见 ulimit -n
)所以你必须增加
如果您希望同时打开 2700 个文件描述符,则此限制。