NLTK没有将$NLTK_DATA添加到搜索路径中?

4
在Linux下,我已经设置了环境变量$NLTK_DATA('/home/user/data/nltk'),并且以下测试按预期工作。
>>> from nltk.corpus import brown
>>> brown.words()
['The', 'Fulton', 'County', 'Grand', 'Jury', 'said', ...]

但是当我运行另一个Python脚本时,出现了以下错误:
LookupError: 
**********************************************************************
Resource u'tokenizers/punkt/english.pickle' not found.  Please
use the NLTK Downloader to obtain the resource:  >>>
nltk.download()
Searched in:
- '/home/user/nltk_data'
- '/usr/share/nltk_data'
- '/usr/local/share/nltk_data'
- '/usr/lib/nltk_data'
- '/usr/local/lib/nltk_data'
- u''

正如我们所看到的,nltk没有将$NLTK_DATA添加到搜索路径中,需要手动添加NLTK_DATA目录后:
nltk.data.path.append("/NLTK_DATA_DIR");

脚本运行如预期,问题是:
如何使nltk自动将$NLTK_DATA添加到其搜索路径中?

由于nltk_data目录是静态的,为什么需要自动查找路径? - alvas
1
默认情况下,NLTK会自动在以下目录中查找nltk_data目录:'/home/user/nltk_data'、'/usr/share/nltk_data'、'/usr/local/share/nltk_data'、'/usr/lib/nltk_data'和'/usr/local/lib/nltk_data'。 - alvas
1
我已经指定了nltk.download()来下载数据到$NLTK_DATA,如果不将$NLTK_DATA添加到搜索目录中,似乎下载的数据无法被脚本使用(但简单命令不能使用)。 - Alex Luya
只要您的脚本中包含 nltk.path.append(),就无需担心 os.environ 中的数据目录问题。请查看更新的答案。 - alvas
nltk确实会将NLTK_DATA路径添加到数据搜索路径中。问题必须由其他原因引起:第二个Python脚本没有继承环境?路径不正确(或可能是相对路径,仅在某些目录中有效)?谁知道呢。但解决方案(适用于任何遇到相同问题的人)是检查和修复变量设置。当nltk看到该变量时,它会自动处理。 - alexis
3个回答

7

如果您不想在运行脚本之前设置$NLTK_DATA,您可以在Python脚本中执行以下操作:

import nltk
nltk.path.append('/home/alvas/some_path/nltk_data/')

例如,让我们将nltk_data移动到非标准路径,NLTK不会自动找到它:
alvas@ubi:~$ ls nltk_data/
chunkers  corpora  grammars  help  misc  models  stemmers  taggers  tokenizers
alvas@ubi:~$ mkdir some_path
alvas@ubi:~$ mv nltk_data/ some_path/
alvas@ubi:~$ ls nltk_data/
ls: cannot access nltk_data/: No such file or directory
alvas@ubi:~$ ls some_path/nltk_data/
chunkers  corpora  grammars  help  misc  models  stemmers  taggers  tokenizers

现在,我们使用nltk.path.append()的方法:
alvas@ubi:~$ python
>>> import os
>>> import nltk
>>> nltk.path.append('/home/alvas/some_path/nltk_data/')
>>> nltk.pos_tag('this is a foo bar'.split())
[('this', 'DT'), ('is', 'VBZ'), ('a', 'DT'), ('foo', 'JJ'), ('bar', 'NN')]
>>> nltk.data
<module 'nltk.data' from '/usr/local/lib/python2.7/dist-packages/nltk/data.pyc'>
>>> nltk.data.path
['/home/alvas/some_path/nltk_data/', '/home/alvas/nltk_data', '/usr/share/nltk_data', '/usr/local/share/nltk_data', '/usr/lib/nltk_data', '/usr/local/lib/nltk_data']
>>> exit()

我们将其移回并查看是否有效:

alvas@ubi:~$ ls nltk_data
ls: cannot access nltk_data: No such file or directory
alvas@ubi:~$ mv some_path/nltk_data/ .
alvas@ubi:~$ python
>>> import nltk
>>> nltk.data.path
['/home/alvas/nltk_data', '/usr/share/nltk_data', '/usr/local/share/nltk_data', '/usr/lib/nltk_data', '/usr/local/lib/nltk_data']
>>> nltk.pos_tag('this is a foo bar'.split())
[('this', 'DT'), ('is', 'VBZ'), ('a', 'DT'), ('foo', 'JJ'), ('bar', 'NN')]

如果您真的非常想自动查找nltk_data,请使用以下方法:

import scandir
import os, sys
import time

import nltk

def find(name, path):
    for root, dirs, files in scandir.walk(path):
        if root.endswith(name):
            return root

def find_nltk_data():
    start = time.time()
    path_to_nltk_data = find('nltk_data', '/')
    print >> sys.stderr, 'Finding nltk_data took', time.time() - start
    print >> sys.stderr,  'nltk_data at', path_to_nltk_data
    with open('where_is_nltk_data.txt', 'w') as fout:
        fout.write(path_to_nltk_data)
    return path_to_nltk_data

def magically_find_nltk_data():
    if os.path.exists('where_is_nltk_data.txt'):
        with open('where_is_nltk_data.txt') as fin:
            path_to_nltk_data = fin.read().strip()
        if os.path.exists(path_to_nltk_data):
            nltk.data.path.append(path_to_nltk_data)
        else:
            nltk.data.path.append(find_nltk_data())
    else:
        path_to_nltk_data  = find_nltk_data()
        nltk.data.path.append(path_to_nltk_data)


magically_find_nltk_data()
print nltk.pos_tag('this is a foo bar'.split())

让我们称之为Python脚本,test.py
alvas@ubi:~$ ls nltk_data/
chunkers  corpora  grammars  help  misc  models  stemmers  taggers  tokenizers
alvas@ubi:~$ python test.py
Finding nltk_data took 4.27330780029
nltk_data at /home/alvas/nltk_data
[('this', 'DT'), ('is', 'VBZ'), ('a', 'DT'), ('foo', 'JJ'), ('bar', 'NN')]
alvas@ubi:~$ mv nltk_data/ some_path/
alvas@ubi:~$ python test.py
Finding nltk_data took 4.75850391388
nltk_data at /home/alvas/some_path/nltk_data
[('this', 'DT'), ('is', 'VBZ'), ('a', 'DT'), ('foo', 'JJ'), ('bar', 'NN')]

有没有一种一站式的方法来解决这个问题,比如添加一个系统变量? - Alex Luya
在导入nltk之后,通过将数据路径附加到“nltk.path.append('/home/alvas/some_path/nltk_data/')”,应该可以解决问题。只是有时用户不知道NLTK目录在哪里,那么您需要使用“magically_find_nltk_data()”。 - alvas
也许我没有表达清楚我的问题。我已经设置了一个名为NLTK_DATA的环境变量,并希望nltk.download()会自动将此目录添加到搜索路径中,并搜索此目录以确定是否已下载内容,如果没有,则下载新内容到此目录,但是nltk.download()没有这样做。问题是如何让nltk识别环境变量NLTK_DATA。 - Alex Luya
在调用Python脚本之前,请在终端中执行以下操作:export NLTK_DATA=/home/alvas/some_path/nltk_data/ - alvas
1
我在Windows上尝试运行时遇到以下错误:nltk.path.append('<我的nltk_data路径>') AttributeError: 模块“nltk”没有属性“path”。 - JON
显示剩余2条评论

0
默认情况下,nltk不会这样做。它会在corpora文件夹中搜索数据。 您必须创建corpora文件夹,然后将您的nltk数据放入其中。 我曾经遇到过同样的问题,不知何故,我下载了nltk数据,结果也是一样。 之后,将nltk.data.path = data_dir添加到解决问题的地方。 这个项目的文件夹结构

根据目前的写法,你的回答不够清晰。请编辑以添加更多细节,以帮助他人理解如何解决所提出的问题。你可以在帮助中心找到关于如何撰写好回答的更多信息。 - undefined

0

如果您想在conda环境中安装NLTK数据,而且不想在每个脚本中指定数据位置或导出环境变量,您需要执行以下操作:

  1. 激活所需的conda环境。
  2. 在conda环境中打印sys.prefix,并复制此路径(假设为/home/dickens/envs/nltk_env)。
  3. 在conda环境中运行nltk.download(),选择所需的软件包,并将/share/nltk_data附加到上述路径作为下载位置。例如,在我们的情况下,它将变为/home/dickens/envs/nltk_env/share/nltk_data
  4. 现在您可以开始使用了!

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接