调用 NLTK 并在 databricks pyspark 上找不到“punkt”错误

Posted

技术标签:

【中文标题】调用 NLTK 并在 databricks pyspark 上找不到“punkt”错误【英文标题】:NLTK is called and got error of "punkt" not found on databricks pyspark 【发布时间】:2020-08-16 04:32:20 【问题描述】:

我想调用 NLTK 来通过 pyspark 在数据块上做一些 NLP。 我已经从 databricks 的库选项卡中安装了 NLTK。它应该可以从所有节点访问。

我的 py3 代码:

 import pyspark.sql.functions as F
 from pyspark.sql.types import StringType
 import nltk
 nltk.download('punkt')
 

 def get_keywords1(col):
     sentences = []
     sentence = nltk.sent_tokenize(col)
      

 get_keywords_udf = F.udf(get_keywords1, StringType())

我运行上面的代码得到:

 [nltk_data] Downloading package punkt to /root/nltk_data...
 [nltk_data]   Package punkt is already up-to-date!

当我运行以下代码时:

 t = spark.createDataFrame(
 [(2010, 1, 'rdc', 'a book'), (2010, 1, 'rdc','a car'),
  (2007, 6, 'utw', 'a house'), (2007, 6, 'utw','a hotel')
 ], 
 ("year", "month", "u_id", "objects"))
 
 t1 = t.withColumn('keywords', get_keywords_udf('objects'))
 t1.show() # error here !

我收到错误:

 <span class="ansi-red-fg">&gt;&gt;&gt; import nltk

 PythonException: 
  An exception was thrown from the Python worker. Please see the stack trace below.
 Traceback (most recent call last):
  
 LookupError: 
 **********************************************************************
 Resource punkt not found.
 Please use the NLTK Downloader to obtain the resource:

 >>> import nltk
 >>> nltk.download('punkt')

 For more information see: https://www.nltk.org/data.html

Attempted to load tokenizers/punkt/PY3/english.pickle

Searched in:
- '/root/nltk_data'
- '/databricks/python/nltk_data'
- '/databricks/python/share/nltk_data'
- '/databricks/python/lib/nltk_data'
- '/usr/share/nltk_data'
- '/usr/local/share/nltk_data'
- '/usr/lib/nltk_data'
- '/usr/local/lib/nltk_data'
- ''

我已经下载了“punkt”。它位于

/root/nltk_data/tokenizers

我已经用文件夹位置更新了 spark 环境中的 PATH。

为什么找不到?

NLTK. Punkt not found 和这个How to config nltk data directory from code? 的解决方案 但它们都不适合我。

我已经尝试更新了

 nltk.data.path.append('/root/nltk_data/tokenizers/')

它不起作用。 好像nltk看不到新添加的路径!

我还将 punkz 复制到 nltk 将搜索的路径。

cp -r /root/nltk_data/tokenizers/punkt /root/nltk_data

但是,nltk 还是看不到它。

谢谢

【问题讨论】:

你检查了所有节点下载该文件吗? 您能告诉我如何检查所有节点吗?谢谢 我有一个类似的问题,你的代码失败的原因是你只在主节点上安装了包,而不是在工作节点上。当您的代码在所有机器上并行运行时,工作节点会出错。您需要找到一种在集群创建/设置期间将下载的文件从主服务器复制到工作服务器的方法,或者如果您的集群可以访问互联网,请在函数中下载它(不是最好的方法,但会解除阻止) @KaranSharma,谢谢,但是,我已经从 databricks 的库选项卡中安装了 NLTK。它应该可以从所有节点访问。 另一个潜在问题可能是因为 nltk 库在每个节点上下载 'punkt' 并且节点可能无法访问 Internet,我会检查集群配置并确保 Internet 可用。您甚至可以在所有节点上运行类似 ping 命令的命令来检查问题。 【参考方案1】:

当启动 Databricks 单节点集群时,这将正常工作。通过 pip 安装 nltk,然后使用 nltk.download 模块获取预构建的模型/文本作品。

假设:用户在 Databricks 笔记本中使用 Python 作为默认语言进行编程。

在启动多节点集群时,您会遇到几个问题。

    您正在注册一个依赖于另一个模块的代码的 UDF。为了使 UDF 在集群中的每个节点上工作,模块需要安装在集群级别(即 nltk 安装在驱动程序和所有工作节点上)。该模块可以像这样在集群启动时通过 init 脚本安装,也可以通过 Databricks Compute 部分中的 library 部分安装。更多信息在这里......(我还在下面给出代码示例) https://docs.microsoft.com/enus/azure/databricks/libraries/cluster-libraries.

    现在,当您运行 UDF 时,该模块将存在于集群的所有节点上。

    使用nltk.download() 获取模块引用的数据。当我们在多节点集群中交互式地执行 nltk.download() 时,它只会下载到驱动程序节点。因此,当您的 UDF 在其他节点上执行时,这些节点将不会在默认情况下查找的指定路径中包含所需的引用。要查看这些路径,默认路径运行nltk.data.path

为了克服这个问题,我探索了两种可能性。其中一个有效。

    (不起作用)使用初始化脚本,安装 nltk,然后在同一个初始化脚本中,在安装后通过单线 bash python 表达式调用 nltk.download...

    python -c 'import nltk; nltk.download('all');'
    

    我遇到了安装 nltk 但安装后找不到的问题。我假设虚拟环境在这里发挥了作用。

    (有效)使用初始化脚本,安装 nltk。

      创建脚本
    dbutils.fs.put('/dbfs/databricks/scripts/nltk-install.sh', """ 
    #!/bin/bash
    pip install nltk""", True)
    
      检查一下
    %sh
    head '/dbfs/databricks/scripts/nltk-install.sh'
    
      配置集群以在启动时运行初始化脚本 Databricks Cluster Init Script Config 在集群配置中创建环境变量 NLTK_DATA="/dbfs/databricks/nltk_data/"。 nltk 包使用它来搜索数据/模型依赖项。 Databricks Cluster Env Variable Config

启动集群。

在安装并运行集群后检查以确保环境变量已正确创建。

import os 
os.environ.get("NLTK_DATA")

然后检查以确保 nltk 指向正确的路径。

import nltk
nltk.data.path

如果 '/dbfs/databricks/nltk_data/ 在列表中,我们很高兴。 下载你需要的东西。

nltk.download('all', download_dir="/dbfs/databricks/nltk_data/")

请注意,我们已将依赖项下载到 Databricks 存储中。现在每个节点都可以访问 nltk 默认依赖项。因为我们在导入 nltk 时在集群创建时指定了环境变量 NLTK_DATA,所以它会在该目录中查找。这里唯一的区别是我们现在将 nltk 指向每个节点都可以访问的 Databricks 存储。

现在,由于数据存在于集群启动时挂载的存储中,我们不需要每次都重新下载数据。

按照这些步骤操作后,您应该已准备好使用 nltk 及其所有默认数据/模型。

【讨论】:

【参考方案2】:

这帮助我解决了问题:

import nltk
nltk.download('all')

【讨论】:

我在 Databricks 上遇到了同样的问题。它并不能解决问题。 :(

以上是关于调用 NLTK 并在 databricks pyspark 上找不到“punkt”错误的主要内容,如果未能解决你的问题,请参考以下文章

nltk包返回TypeError:'LazyCorpusLoader'对象不可调用

NLTK 中用于解析的英语语法

运行时出现NLTK Python错误

cannot import name dispersion_plot----------nltk小bug

在Windows10 Pro上安装NLTK时出错

尝试在 Databricks 上安装 H2O。如何在 Databricks 中安装 3rd 方包?