我在AWS lambda中遇到NLTK软件包的问题。但是,我认为这个问题与Lambda中的路径配置更多有关。NLTK在寻找本地存储而不是模块安装的一部分的数据库困难。在这里可以找到的许多解决方案都是简单的路径配置,但我认为此问题与lambda中的路径有关:
如何从代码配置NLTK数据目录?
为了制作nltk.tokenize.word_tokenize工作?
也应该提到这也与我在此处发布的以前的问题有关在Python中使用NLTK Corpora和AWS lambda函数
,但这个问题似乎更笼统,因此我选择重新定义该问题,因为它如何正确配置Lambda中的路径环境以与需要NLTK等外部库的模块配合使用。NLTK将许多数据存储在本地的NLTK_DATA文件夹中,但是在Lambda zip中包括此文件夹以进行上传,似乎找不到它。
在lambda func zip文件中还包括以下文件和dirs:
nltk_datataggersaveraged_perceptron_taggeraveraged_perceptron_tagger.pickle
nltk_datatokenizerspunktenglish.pickle
nltk_datatokenizerspunktPY3english.pickle
从以下站点中,var/task/似乎是lambda函数执行的文件夹,我尝试包括此路径无用。https://alacen.com/2014/11/aws-lambda-environment/
从文档中看来,似乎有许多可以使用的环境变量,但是我不确定如何将它们包含在python脚本中(来自Windows而不是Linux)http://docs.aws.amazon.com/lambda/lambda/lambda/drest/dg/current-supported-versions.html
希望在此处扔掉这个问题,即任何人都有配置lambda路径的经验。尽管搜索了搜索,但我还没有看到与这个特定问题有关的很多问题,因此希望解决此问题可能很有用
代码在这里
import nltk
import pymysql.cursors
import re
import rds_config
import logging
from boto_conn import botoConn
from warnings import filterwarnings
from nltk import word_tokenize
nltk.data.path.append("/nltk_data/tokenizers/punkt")
nltk.data.path.append("/nltk_data/taggers/averaged_perceptron_tagger")
logger = logging.getLogger()
logger.setLevel(logging.INFO)
rds_host = "nodexrd2.cw7jbiq3uokf.ap-southeast-2.rds.amazonaws.com"
name = rds_config.db_username
password = rds_config.db_password
db_name = rds_config.db_name
filterwarnings("ignore", category=pymysql.Warning)
def parse():
tknzr = word_tokenize
stopwords = ['i', 'me', 'my', 'myself', 'we', 'our', 'ours', 'ourselves', 'you', 'your', 'yours', 'yourself','yourselves', 'he', 'him', 'his', 'himself', 'she', 'her', 'hers', 'herself', 'it', 'its', 'itself',
'they', 'them', 'their', 'theirs', 'themselves', 'what', 'which', 'who', 'whom', 'this', 'that','these','those', 'am', 'is', 'are', 'was', 'were', 'be', 'been', 'being', 'have', 'has', 'had', 'having', 'do',
'does', 'did', 'doing', 'a', 'an', 'the', 'and', 'but', 'if', 'or', 'because', 'as', 'until', 'while', 'of','at', 'by', 'for', 'with', 'about', 'against', 'between', 'into', 'through', 'during', 'before', 'after', 'above',
'below','to', 'from', 'up', 'down', 'in', 'out', 'on', 'off', 'over', 'under', 'again', 'further', 'then','once', 'here','there', 'when', 'where', 'why', 'how', 'all', 'any', 'both', 'each', 'few', 'more', 'most', 'other',
'some', 'such','no', 'nor', 'not', 'only', 'own', 'same', 'so', 'than', 'too', 'very', 's', 't', 'can', 'will','just', 'don', 'should','now', 'd', 'll', 'm', 'o', 're', 've', 'y', 'ain', 'aren', 'couldn', 'didn', 'doesn', 'hadn', 'hasn',
'haven', 'isn', 'ma','mightn', 'mustn', 'needn', 'shan', 'shouldn', 'wasn', 'weren', 'won', 'wouldn']
s3file = botoConn(None, 1).getvalue()
db = pymysql.connect(rds_host, user=name, passwd=password, db=db_name, connect_timeout=5, charset='utf8mb4', cursorclass=pymysql.cursors.DictCursor)
lines = s3file.split('n')
for line in lines:
tkn = tknzr(line)
tagged = nltk.pos_tag(tkn)
excl = ['the', 'and', 'of', 'at', 'what', 'to', 'it', 'a', 'of', 'i', 's', 't', 'is', 'I'm', 'Im', 'U', 'RT', 'RTs', 'its'] # Arg
x = [i for i in tagged if i[0] not in stopwords]
x = [i for i in x if i[0] not in excl]
x = [i for i in x if len(i[0]) > 1]
x = [i for i in x if 'https' not in i[0]]
x = [i for i in x if i[1] == 'NNP' or i[1] == 'VB' or i[1] == 'NN']
x = [(re.sub(r'[^A-Za-z0-9]+' + '()', r'', i[0])) for i in x]
sql_dat_a, sql_dat = [], []
输出日志在这里:
**********************************************************************
Resource u'tokenizers/punkt/english.pickle' not found. Please
use the NLTK Downloader to obtain the resource: >>>
nltk.download()
Searched in:
- '/home/sbx_user1067/nltk_data'
- '/usr/share/nltk_data'
- '/usr/local/share/nltk_data'
- '/usr/lib/nltk_data'
- '/usr/local/lib/nltk_data'
- '/nltk_data/tokenizers/punkt'
- '/nltk_data/taggers/averaged_perceptron_tagger'
- u''
**********************************************************************: LookupError
Traceback (most recent call last):
File "/var/task/Tweetscrape_Timer.py", line 27, in schedule
server()
File "/var/task/Tweetscrape_Timer.py", line 14, in server
parse()
File "/var/task/parse_to_SQL.py", line 91, in parse
tkn = tknzr(line)
File "/var/task/nltk/tokenize/__init__.py", line 109, in word_tokenize
return [token for sent in sent_tokenize(text, language)
File "/var/task/nltk/tokenize/__init__.py", line 93, in sent_tokenize
tokenizer = load('tokenizers/punkt/{0}.pickle'.format(language))
File "/var/task/nltk/data.py", line 808, in load
opened_resource = _open(resource_url)
File "/var/task/nltk/data.py", line 926, in _open
return find(path_, path + ['']).open()
File "/var/task/nltk/data.py", line 648, in find
raise LookupError(resource_not_found)
LookupError:
**********************************************************************
Resource u'tokenizers/punkt/english.pickle' not found. Please
use the NLTK Downloader to obtain the resource: >>>
nltk.download()
Searched in:
- '/home/sbx_user1067/nltk_data'
- '/usr/share/nltk_data'
- '/usr/local/share/nltk_data'
- '/usr/lib/nltk_data'
- '/usr/local/lib/nltk_data'
- '/nltk_data/tokenizers/punkt'
- '/nltk_data/taggers/averaged_perceptron_tagger'
- u''
**********************************************************************
似乎您当前的Python代码从/var/task
运行。我建议尝试(没有尝试过):
nltk.data.path.append("/var/task/nltk_data")
,所以我找到了这个问题的答案。几天后,我终于弄清楚了。NLTK文件夹中的data.py文件需要如下修改。基本上删除/usr/...路径,然后添加lambda从/var/task/执行的文件夹,并确保您的nltk_data文件夹位于执行zip的根部。
不确定为什么,但是使用inline nltk.data.path.append()方法不适用于AWS lambda,并且需要直接修改data.py文件。
else:
# Common locations on UNIX & OS X:
path += [
str('/var/task/nltk_data')
#str('/usr/share/nltk_data'),
#str('/usr/local/share/nltk_data'),
#str('/usr/lib/nltk_data'),
#str('/usr/local/lib/nltk_data')
]
有点晚,但是如果您贴上粘贴的片段之上,则NLTK库(v.3.2.2)使您能够将自己的自定义路径添加到搜索的路径数组。
# User-specified locations:
_paths_from_env = os.environ.get('NLTK_DATA', str('')).split(os.pathsep)
path += [d for d in _paths_from_env if d]
因此,既然lambda允许您添加自己的环境变量,则可以在部署功能时将NLTK_DATA环境变量设置为/var/task/nltk_data
,并且应该可以工作。我还没有在lambda上测试过。
我不确定lambda在发布此问题时是否允许环境变量,但现在应该可行。
编辑1 通过我部署到lambda的一些Python应用程序对此进行重新访问,我使用了上面Matt提供的解决方案,它对我有用。
nltk.data.path.append("/var/task/nltk_data")
在调用任何需要NLTK Corpora的功能之前,您需要记住
import nltk
此外,需要在NLTK_DATA子目录中下载和安装您的项目(根据上述.append方法)。
如果在AWS CodeBuild中使用Virtualenv,则buildSpec.yml代码片将看起来像:
pre_build:
commands:
...
- export HOME_DIR=`pwd`
- mkdir $HOME_DIR/nltk_data/
- export NLTK_DATA=$HOME_DIR/nltk_data
- $VIRTUAL_ENV/bin/python2.7 -m nltk.downloader -d $NLTK_DATA punkt
...
看来nltk
源代码正在检查是否存在nltk.data.path
的目录,否则将默认为用户home的子目录。
在lambda中,虽然您可以写入/tmp
,但最初将不存在子目录(与/var/task相同)。因此,即使否则可以使用该目录,它也会失败并绕过目录。
you 可以按照提到的@praxis更改nltk
源代码,还有另一个不需要的解决方案。
nltk.download
采用一个可选的命名参数download_dir
,只需将其设置为/tmp/nltk_data
,下载效果很好。
示例:
nltk.download('stopwords', download_dir='/tmp/nltk_data')