【问题标题】:nltk StanfordNERTagger : NoClassDefFoundError: org/slf4j/LoggerFactory (In Windows)nltk StanfordNERTagger : NoClassDefFoundError: org/slf4j/LoggerFactory (在 Windows 中)
【发布时间】:2015-12-18 18:20:22
【问题描述】:

注意:我使用 Python 2.7 作为 Anaconda 发行版的一部分。我希望这对 nltk 3.1 来说不是问题。

我正在尝试将 nltk 用于 NER

import nltk
from nltk.tag.stanford import StanfordNERTagger 
#st = StanfordNERTagger('stanford-ner/all.3class.distsim.crf.ser.gz', 'stanford-ner/stanford-ner.jar')
st = StanfordNERTagger('english.all.3class.distsim.crf.ser.gz') 
print st.tag(str)

但我明白了

Exception in thread "main" java.lang.NoClassDefFoundError: org/slf4j/LoggerFactory
    at edu.stanford.nlp.io.IOUtils.<clinit>(IOUtils.java:41)
    at edu.stanford.nlp.ie.AbstractSequenceClassifier.classifyAndWriteAnswers(AbstractSequenceClassifier.java:1117)
    at edu.stanford.nlp.ie.AbstractSequenceClassifier.classifyAndWriteAnswers(AbstractSequenceClassifier.java:1076)
    at edu.stanford.nlp.ie.AbstractSequenceClassifier.classifyAndWriteAnswers(AbstractSequenceClassifier.java:1057)
    at edu.stanford.nlp.ie.crf.CRFClassifier.main(CRFClassifier.java:3088)
Caused by: java.lang.ClassNotFoundException: org.slf4j.LoggerFactory
    at java.net.URLClassLoader.findClass(URLClassLoader.java:381)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
    at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:331)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
    ... 5 more

Traceback (most recent call last):
  File "X:\jnk.py", line 47, in <module>
    print st.tag(str)
  File "X:\Anaconda2\lib\site-packages\nltk\tag\stanford.py", line 66, in tag
    return sum(self.tag_sents([tokens]), []) 
  File "X:\Anaconda2\lib\site-packages\nltk\tag\stanford.py", line 89, in tag_sents
    stdout=PIPE, stderr=PIPE)
  File "X:\Anaconda2\lib\site-packages\nltk\internals.py", line 134, in java
    raise OSError('Java command failed : ' + str(cmd))
OSError: Java command failed : ['X:\\PROGRA~1\\Java\\JDK18~1.0_6\\bin\\java.exe', '-mx1000m', '-cp', 'X:\\stanford\\stanford-ner.jar', 'edu.stanford.nlp.ie.crf.CRFClassifier', '-loadClassifier', 'X:\\stanford\\classifiers\\english.all.3class.distsim.crf.ser.gz', '-textFile', 'x:\\appdata\\local\\temp\\tmpqjsoma', '-outputFormat', 'slashTags', '-tokenizerFactory', 'edu.stanford.nlp.process.WhitespaceTokenizer', '-tokenizerOptions', '"tokenizeNLs=false"', '-encoding', 'utf8']

但我可以看到 slf4j jar 在我的 lib 文件夹中。我需要更新环境变量吗?

编辑

感谢大家的帮助,但我仍然遇到同样的错误。这是我最近尝试过的

import nltk
from nltk.tag import StanfordNERTagger 
print(nltk.__version__)
stanford_ner_dir = 'X:\\stanford\\'
eng_model_filename= stanford_ner_dir + 'classifiers\\english.all.3class.distsim.crf.ser.gz'
my_path_to_jar= stanford_ner_dir + 'stanford-ner.jar'
st = StanfordNERTagger(model_filename=eng_model_filename, path_to_jar=my_path_to_jar) 
print st._stanford_model
print st._stanford_jar

st.tag('Rami Eid is studying at Stony Brook University in NY'.split())

还有

import nltk
from nltk.tag import StanfordNERTagger 
print(nltk.__version__)
st = StanfordNERTagger('english.all.3class.distsim.crf.ser.gz') 
print st._stanford_model
print st._stanford_jar
st.tag('Rami Eid is studying at Stony Brook University in NY'.split())

我明白了

3.1
X:\stanford\classifiers\english.all.3class.distsim.crf.ser.gz
X:\stanford\stanford-ner.jar

之后它继续打印与以前相同的堆栈跟踪。 java.lang.ClassNotFoundException: org.slf4j.LoggerFactory

知道为什么会发生这种情况吗?我也更新了我的 CLASSPATH。我什至将所有相关文件夹添加到我的 PATH 环境变量中。例如,我解压缩 stanford jar 的文件夹、解压缩 slf4j 的位置,甚至是 stanford 文件夹内的 lib 文件夹。我不知道为什么会这样:(

会是窗户吗?我之前遇到过 Windows 路径问题

更新

  1. 我拥有的斯坦福 NER 版本是 3.6.0。压缩文件显示stanford-ner-2015-12-09.zip

  2. 我也尝试使用 stanford-ner-3.6.0.jar 而不是 stanford-ner.jar,但仍然遇到同样的错误

  3. 当我右击stanford-ner-3.6.0.jar时,我注意到了

我在我提取的所有文件中都看到了这一点,甚至是 slf4j 文件。这会导致问题吗?

  1. 最后,为什么会出现错误提示

java.lang.NoClassDefFoundError: org/slf4j/LoggerFactory

我在任何地方都没有看到任何名为 org 的文件夹

更新:环境变量

这是我的环境变量

CLASSPATH
.;
X:\jre1.8.0_60\lib\rt.jar;
X:\stanford\stanford-ner-3.6.0.jar;
X:\stanford\stanford-ner.jar;
X:\stanford\lib\slf4j-simple.jar;
X:\stanford\lib\slf4j-api.jar;
X:\slf4j\slf4j-1.7.13\slf4j-1.7.13\slf4j-log4j12-1.7.13.jar

STANFORD_MODELS
X:\stanford\classifiers

JAVA_HOME
X:\PROGRA~1\Java\JDK18~1.0_6

PATH
X:\PROGRA~1\Java\JDK18~1.0_6\bin;
X:\stanford;
X:\stanford\lib;
X:\slf4j\slf4j-1.7.13\slf4j-1.7.13

这里有什么问题吗?

【问题讨论】:

  • 当我运行您的示例脚本时,我收到错误“”“设置 CLASSPATH 环境变量。”“”所以是的,我认为您需要更新它
  • classpath 已经指向解压 stanford 资料的文件夹。我想知道是否还应该在类路径中添加 lib 文件夹的路径
  • lib 文件夹也需要在 CLASSPATH 中。
  • @AbtPst,你让它工作了吗?我在 Mac OS X El Capitan 上遇到了同样的问题。首先它给了我UnsupportedClassVersionError,这让我将java 7升级到8,然后它给了我这个错误。

标签: python windows nlp nltk stanford-nlp


【解决方案1】:

已编辑

注意:以下答案仅适用于:

  • NLTK 3.1 版
  • 自 2015 年 4 月 20 日起编译的斯坦福工具

由于这两种工具的变化都相当快,而且 API 可能在 3-6 个月后看起来会大不相同。请将以下答案视为暂时的,而不是永恒的解决方案。

有关如何使用 NLTK 连接斯坦福 NLP 工具的最新说明,请始终参考 https://github.com/nltk/nltk/wiki/Installing-Third-Party-Software!!


第一步

首先使用将您的 NLTK 更新到 3.1 版

pip install -U nltk

或(对于 Windows)使用 http://pypi.python.org/pypi/nltk 下载最新的 NLTK

然后使用以下命令检查您是否拥有 3.1 版:

python3 -c "import nltk; print(nltk.__version__)"

第 2 步

然后从http://nlp.stanford.edu/software/stanford-ner-2015-04-20.zip下载zip文件并解压文件并保存到C:\some\path\to\stanford-ner\(在windows中)

第三步

然后将CLASSPATH的环境变量设置为C:\some\path\to\stanford-ner\stanford-ner.jar

STANFORD_MODELS 的环境变量 C:\some\path\to\stanford-ner\classifiers

或在命令行中(仅适用于 Windows):

set CLASSPATH=%CLASSPATH%;C:\some\path\to\stanford-ner\stanford-ner.jar
set STANFORD_MODELS=%STANFORD_MODELS%;C:\some\path\to\stanford-ner\classifiers

(有关在 Windows 中设置环境变量的点击 GUI 说明,请参阅 https://stackoverflow.com/a/17176423/610569

(有关在 Linux 中设置环境变量的详细信息,请参阅Stanford Parser and NLTK

第四步

然后在python中:

>>> from nltk.tag import StanfordNERTagger
>>> st = StanfordNERTagger('english.all.3class.distsim.crf.ser.gz') 
>>> st.tag('Rami Eid is studying at Stony Brook University in NY'.split())
[(u'Rami', u'PERSON'), (u'Eid', u'PERSON'), (u'is', u'O'), (u'studying', u'O'), (u'at', u'O'), (u'Stony', u'ORGANIZATION'), (u'Brook', u'ORGANIZATION'), (u'University', u'ORGANIZATION'), (u'in', u'O'), (u'NY', u'O')]

不设置环境变量,可以试试:

from nltk.tag import StanfordNERTagger

stanford_ner_dir = 'C:\\some\path\to\stanford-ner\'
eng_model_filename= stanford_ner_dir + 'classifiers\english.all.3class.distsim.crf.ser.gz'
my_path_to_jar= stanford_ner_dir + 'stanford-ner.jar'

st = StanfordNERTagger(model_filename=eng_model_filename, path_to_jar=my_path_to_jar) 
st.tag('Rami Eid is studying at Stony Brook University in NY'.split())

Stanford Parser and NLTK上查看更多详细说明

【讨论】:

  • 感谢您的详细解释。我尝试了你的方法,但我仍然得到错误。请查看编辑
  • 你试过set CLASSPATH=%CLASSPATH%;C:\some\path\to\stanford-ner\stanford-ner.jarset STANFORD_MODELS=%STANFORD_MODELS%;C:\some\path\to\stanford-ner\classifiers
  • 你能在你的windows命令行上运行这个吗:X:\\PROGRA~1\\Java\\JDK18~1.0_6\\bin\\java.exe -mx1000m -cp X:\\stanford\\stanford-ner.jar edu.stanford.nlp.ie.crf.CRFClassifier -loadClassifier X:\\stanford\\classifiers\\english.all.3class.distsim.crf.ser.gz -textFile x:\\appdata\\local\\temp\\tmpqjsoma -outputFormat slashTags -tokenizerFactory edu.stanford.nlp.process.WhitespaceTokenizer -tokenizerOptions "tokenizeNLs=false" -encoding utf8 ?
  • 如需快速修复,请使用nlp.stanford.edu/software/stanford-ner-2015-04-20.zip。稍后我会尝试更新 2015-12-09 的答案。
  • 使用 stanford-ner-2015-04-20 时,它适用于 python2.7 和 python3。但这是 NLTK 追赶斯坦福 API 的追赶游戏。
【解决方案2】:

我遇到了和你昨天描述的完全一样的问题。

你需要做 3 件事。

1) 更新您的 NLTK。

pip install -U nltk

你的版本应该是 >3.1 我看到你正在使用

from nltk.tag.stanford import StanfordNERTagger

但是,您必须使用新模块:

from nltk.tag import StanfordNERTagger

2) 下载 slf4j 并更新您的 CLASSPATH。

这是更新 CLASSPATH 的方法。

javapath = "/Users/aerin/Downloads/stanford-ner-2014-06-16/stanford-ner.jar:/Users/aerin/java/slf4j-1.7.13/slf4j-log4j12-1.7.13.jar"
os.environ['CLASSPATH'] = javapath 

如您所见,javapath包含2个路径,一个是stanford-ner.jar所在的位置,另一个是您下载slf4j-log4j12-1.7.13.jar的位置(可以在这里下载:http://www.slf4j.org/download.html

3) 不要忘记指明您下载“english.all.3class.dissim.crf.ser.gz”和“stanford-ner.jar”的位置

st = StanfordNERTagger('/Users/aerin/Downloads/stanford-ner-2014-06-16/classifiers/english.all.3class.distsim.crf.ser.gz','/Users/aerin/Downloads/stanford-ner-2014-06-16/stanford-ner.jar') 

st.tag("Doneyo lab did such an awesome job!".split())

【讨论】:

  • 感谢您的详细解释。我尝试了你的方法,但我仍然得到错误。请查看编辑
  • 请查看编辑,我添加了有关我的环境变量的详细信息。
  • 感谢@doneyo 的帮助,但看起来问题出在我使用的 stanford ner 版本上。
  • @AbtPst 您是否尝试过“2015-01-30”版本,而不是 10 天前的版本?一月版本不会抛出 slf4j/LoggerFactory 错误。
【解决方案3】:

注意:

下面是一个可以使用的临时技巧:

  • NLTK 3.1 版
  • 斯坦福 NER 编译于 2015 年 12 月 9 日

此解决方案不是旨在成为永恒的解决方案。

有关如何使用 NLTK 连接斯坦福 NLP 工具的最新说明,请始终参考 https://github.com/nltk/nltk/wiki/Installing-Third-Party-Software!!

如果您不想使用此“黑客”:https://github.com/nltk/nltk/issues/1237,请跟踪有关此问题的更新,或者请使用 2015 年 4 月 20 日编译的 NER 工具。


简而言之

确保您拥有:

  • NLTK 3.1 版
  • 斯坦福 NER 编译于 2015 年 12 月 9 日
  • CLASSPATHSTANFORD_MODELS设置环境变量

在 Windows 中设置环境变量:

set CLASSPATH=%CLASSPATH%;C:\some\path\to\stanford-ner\stanford-ner.jar
set STANFORD_MODELS=%STANFORD_MODELS%;C:\some\path\to\stanford-ner\classifiers

在 Linux 中设置环境变量:

export STANFORDTOOLSDIR=/home/some/path/to/stanfordtools/
export CLASSPATH=$STANFORDTOOLSDIR/stanford-ner-2015-12-09/stanford-ner.jar
export STANFORD_MODELS=$STANFORDTOOLSDIR/stanford-ner-2015-12-09/classifiers

然后:

>>> from nltk.internals import find_jars_within_path
>>> from nltk.tag import StanfordNERTagger
>>> st = StanfordNERTagger('english.all.3class.distsim.crf.ser.gz') 
# Note this is where your stanford_jar is saved.
# We are accessing the environment variables you've 
# set through the NLTK API.
>>> print st._stanford_jar
/home/alvas/stanford-ner-2015-12-09/stanford-ner.jar
>>> stanford_dir = st._stanford_jar.rpartition("\\")[0] # windows
# Note in linux you do this instead: 
>>> stanford_dir = st._stanford_jar.rpartition('/')[0] # linux
# Use the `find_jars_within_path` function to get all the
# jar files out from stanford NER tool under the libs/ dir.
>>> stanford_jars = find_jars_within_path(stanford_dir)
# Put the jars back into the `stanford_jar` classpath.
>>> st._stanford_jar = ':'.join(stanford_jars) # linux
>>> st._stanford_jar = ';'.join(stanford_jars) # windows
>>> st.tag('Rami Eid is studying at Stony Brook University in NY'.split())
[(u'Rami', u'PERSON'), (u'Eid', u'PERSON'), (u'is', u'O'), (u'studying', u'O'), (u'at', u'O'), (u'Stony', u'ORGANIZATION'), (u'Brook', u'ORGANIZATION'), (u'University', u'ORGANIZATION'), (u'in', u'O'), (u'NY', u'O')]

【讨论】:

    【解决方案4】:

    我修好了!

    你应该在CLASSPATH中指明slf4j-api.jar的完整路径

    您可以在代码中这样做,而不是将 jar-path 添加到系统环境变量中:

    _CLASS_PATH = "."    
    if os.environ.get('CLASSPATH') is not None:
        _CLASS_PATH = os.environ.get('CLASSPATH')
    os.environ['CLASSPATH'] = _CLASS_PATH + ';F:\Python\Lib\slf4j\slf4j-api-1.7.13.jar'
    

    重要,在 nltk/*/stanford.py 中会像这样重置类路径:

    stdout, stderr = java(cmd, classpath=self._stanford_jar, stdout=PIPE, stderr=PIPE)
    

    例如。 \Python34\Lib\site-packages\nltk\tokenize\stanford.py 行:90

    你可以这样修复它:

    _CLASS_PATH = "."
    if os.environ.get('CLASSPATH') is not None:
        _CLASS_PATH = os.environ.get('CLASSPATH')
    stdout, stderr = java(cmd, classpath=(self._stanford_jar, _CLASS_PATH), stdout=PIPE, stderr=PIPE)
    

    【讨论】:

      【解决方案5】:

      当前的斯坦福 NER 标记器版本与 nltk 不兼容,因为它需要 nltk 无法添加到 CLASSPATH 的额外 jar。

      而是更喜欢旧版本的斯坦福 NER Tagger,它可以像这样完美地工作:http://nlp.stanford.edu/software/stanford-ner-2015-04-20.zip

      【讨论】:

        【解决方案6】:

        对于那些想要使用 Stanford NER >= 3.6.0 而不是 2015-01-30 (3.5.1) 或其他旧版本的用户,请改为:

        1. 把stanford-ner.jar和slf4j-api.jar放到同一个文件夹

          比如我把以下文件放到/path-to-libs/

          • stanford-ner-3.6.0.jar
          • slf4j-api-1.7.18.jar
        2. 然后:

          classpath = "/path-to-libs/*"
          
          st = nltk.tag.StanfordNERTagger(
              "/path-to-model/ner-model.ser.gz",
              "/path-to-libs/stanford-ner-3.6.0.jar"
          )
          st._stanford_jar = classpath
          result = st.tag(["Hello"])
          

        【讨论】:

          【解决方案7】:

          我认为问题在于slf4j 的使用方式。

          我正在使用 nltk 3.1 并使用 stanford-parser-full-2015-12-09。我唯一能让它工作的方法是修改/Library/Python/2.7/site-packages/nltk/parse/stanford.py 并将slf4j jar 添加到self._classpathinit 方法中。

          解决了。粗略 - 但 - 有效。

          注意 - 我并没有完全尝试 NER。我正在尝试类似下面的东西

          import os
          from nltk.parse import stanford
          os.environ['STANFORD_PARSER'] = '/Users/run2/stanford-parser-full-2015-12-09'
          os.environ['STANFORD_MODELS'] = '/Users/run2/stanford-parser-full-2015-12-09'
          parser = stanford.StanfordParser(model_path='/Users/run2/stanford-parser-full-2015-12-09/englishPCFG.ser.gz')
          sentences = parser.raw_parse_sents('<some sentence from my corpus>')
          

          【讨论】:

          • 否 - 这不起作用,因为 stanford.py 对类路径 jar 进行硬编码
          • 这不是真的,您可以通过编辑st._stanford_jar 来覆盖jar 路径。看看github.com/nltk/nltk/blob/develop/nltk/tag/stanford.py#L50 那是添加jar 文件的那一行。您使用的是哪个 NLTK 版本?
          • 这里有一个更具体的 StanfordNERTagger 解决方案:gist.github.com/alvations/e1df0ba227e542955a8a
          • 嗨 alvas - 如前所述,我使用的是 nltk 3.1。嗯 - 是的 - 你可以用很多方法来做(一旦你编辑了我所做的那个文件)。对我来说,编辑第 64 行似乎更合乎逻辑。 self._classpath = (stanford_jar, model_jar, '/Users/run2/stanford-parser-full-2015-12-09/slf4j-api.jar')
          【解决方案8】:

          据我所知,您的代码中没有为 python 设置java environment

          您可以使用以下代码来做到这一点:

          from nltk.tag.stanford import NERTagger
          import os
          java_path = "/Java/jdk1.8.0_45/bin/java.exe"
          os.environ['JAVAHOME'] = java_path
          st = NERTagger('../ner-model.ser.gz','../stanford-ner.jar')
          tagging = st.tag(text.split())   
          

          检查这是否解决了您的问题。

          【讨论】:

          • 我认为这不是问题所在。因为如果java没有正确初始化,Java Exception就不会出现。
          【解决方案9】:

          最好的办法就是下载最新版本的斯坦福 NER 标记器,现在已修复依赖问题(2018 年 3 月)。

          wget https://nlp.stanford.edu/software/stanford-ner-2018-02-27.zip
          

          【讨论】:

            猜你喜欢
            • 2015-11-30
            • 2010-12-13
            • 1970-01-01
            • 2016-04-20
            • 1970-01-01
            • 1970-01-01
            • 2014-12-15
            • 2017-02-06
            • 2017-09-04
            相关资源
            最近更新 更多