Nltk: マルチプロセッシングとnltkはうまく連携しません

作成日 2015年04月16日  ·  22コメント  ·  ソース: nltk/nltk

正直なところ、この問題は好奇心が強いほど深刻ではありません。 NLTKをインポートすると、Pythonサブプロセスがネットワーク呼び出しで途中で終了することがわかりました。 コード例:

from multiprocessing import Process
import nltk
import time


def child_fn():
    print "Fetch URL"
    import urllib2
    print urllib2.urlopen("https://www.google.com").read()[:100]
    print "Done"


while True:
    child_process = Process(target=child_fn)
    child_process.start()
    child_process.join()
    print "Child process returned"
    time.sleep(1)

NLTKをインポートして実行すると、urlopen()呼び出しが実行されないことがわかります。 import nltk行をコメントアウトすると、正常に実行されます。

どうして?

*編集:これはPython2用です。3ではまだテストしていません。

admin bug inactive multithread / multiprocessing pythonic

最も参考になるコメント

私はnltkにあまり詳しくありませんが、テストの合格/不合格の原因を確認するために少しブラインドを突っ込みました。 テストに合格するために、パッケージ__init__.pyに対して行う必要があることは次のとおりです。


詳細(クリックして展開)

###########################################################
# TOP-LEVEL MODULES
###########################################################

# Import top-level functionality into top-level namespace

from nltk.collocations import *
from nltk.decorators import decorator, memoize
# from nltk.featstruct import *
# from nltk.grammar import *
from nltk.probability import *
from nltk.text import *
# from nltk.tree import *
from nltk.util import *
from nltk.jsontags import *

# ###########################################################
# # PACKAGES
# ###########################################################

# from nltk.chunk import *
# from nltk.classify import *
# from nltk.inference import *
from nltk.metrics import *
# from nltk.parse import *
# from nltk.tag import *
from nltk.tokenize import *
from nltk.translate import *
# from nltk.sem import *
# from nltk.stem import *

# Packages which can be lazily imported
# (a) we don't import *
# (b) they're slow to import or have run-time dependencies
#     that can safely fail at run time

from nltk import lazyimport
app = lazyimport.LazyModule('nltk.app', locals(), globals())
chat = lazyimport.LazyModule('nltk.chat', locals(), globals())
corpus = lazyimport.LazyModule('nltk.corpus', locals(), globals())
draw = lazyimport.LazyModule('nltk.draw', locals(), globals())
toolbox = lazyimport.LazyModule('nltk.toolbox', locals(), globals())

# Optional loading

try:
    import numpy
except ImportError:
    pass
else:
    from nltk import cluster

# from nltk.downloader import download, download_shell
# try:
#     from six.moves import tkinter
# except ImportError:
#     pass
# else:
#     try:
#         from nltk.downloader import download_gui
#     except RuntimeError as e:
#         import warnings
#         warnings.warn("Corpus downloader GUI not loaded "
#                       "(RuntimeError during import: %s)" % str(e))

# explicitly import all top-level modules (ensuring
# they override the same names inadvertently imported
# from a subpackage)

# from nltk import ccg, chunk, classify, collocations
# from nltk import data, featstruct, grammar, help, inference, metrics
# from nltk import misc, parse, probability, sem, stem, wsd
# from nltk import tag, tbl, text, tokenize, translate, tree, treetransforms, util


興味深いことに、無効にされたすべてのインポートは、最終的にtkinterインポートに戻ります。これが、根本的な原因だと思います。 テストスクリプトでimport nltkimport tkinterに置き換えると、非常によく似たクラッシュレポートが表示され、どちらもtkinterを参照しています。

私の知る限り、これらのパッケージはtkinter直接インポートします。

  • nltk.app
  • nltk.draw
  • nltk.sem

上記のメインパッケージ__init__への変更から、これらは問題のあるインポートであり、tkinterのインポートにどのようにさかのぼりますか

  • nltk.featstructsem
  • nltk.grammarfeatstruct
  • nltk.treegrammar
  • nltk.chunkchunk.named_entity > tree
  • nltk.parseparse.bllip > tree
  • nltk.tagtag.stanford > parse
  • nltk.classifyclassify.senna > tag
  • nltk.inferenceinference.discourse > semtag
  • nltk.stemstem.snowball > corpus > corpus.reader.timit > tree

全てのコメント22件

例外はありますか?

番号。 import urllib2; print...周りにtry .. except:句を配置しましたが、何も得られませんでした。

私はまったく同じ問題に直面しています。 ここにリンクするのに役立つかもしれないSOの質問を開いたところです: http

子プロセスは実際、通知なしにサイレントにクラッシュしています。

@ oxymor0nに同意しません、これは私にとって非常に深刻な問題のようです。 これは基本的に、nltkがインポートされるたびに、APIを操作するときに非常に煩わしい子プロセスからリクエストを発行する方法がないことを意味します。

The child process is indeed crashing silently without further notice.

この問題は、nltk、gunicorn(nltkがプリフォークを介してロードされている)、およびフラスコの組み合わせでも発生しています。

nltkインポートを削除すると、すべてが機能します。 nltkを除く。

/ cc @escherba

@ ninowalker@ oxymor0n奇妙なことに、私のプロセスはコードで正常に実行されます。

Fetch URL
<!doctype html><html itemscope="" itemtype="http://schema.org/WebPage" lang="de"><head><meta content
Done
Child process returned
Fetch URL
<!doctype html><html itemscope="" itemtype="http://schema.org/WebPage" lang="de"><head><meta content
Done
Child process returned
Fetch URL
<!doctype html><html itemscope="" itemtype="http://schema.org/WebPage" lang="de"><head><meta content
Done
Child process returned
Fetch URL
<!doctype html><html itemscope="" itemtype="http://schema.org/WebPage" lang="de"><head><meta content
Done
Child process returned
Fetch URL
<!doctype html><html itemscope="" itemtype="http://schema.org/WebPage" lang="de"><head><meta content
Done
Child process returned
Fetch URL
<!doctype html><html itemscope="" itemtype="http://schema.org/WebPage" lang="de"><head><meta content
Done
Child process returned
Fetch URL
<!doctype html><html itemscope="" itemtype="http://schema.org/WebPage" lang="de"><head><meta content
Done
Child process returned

それが期待される出力ですよね?

これでも私の要求を壊すことはありません:

alvas<strong i="13">@ubi</strong>:~$ python
Python 2.7.6 (default, Jun 22 2015, 17:58:13) 
[GCC 4.8.2] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> from multiprocessing import Process
>>> import requests
>>> from pprint import pprint
>>> Process(target=lambda: pprint(
...         requests.get('https://api.github.com'))).start()
>>> <Response [200]>

>>> import nltk
>>> Process(target=lambda: pprint(
...         requests.get('https://api.github.com'))).start()
>>> <Response [200]>

私が使用しているもの:

  • Python 2.7.6
  • nltk 3.0.3
  • ubuntu 14.04

@Hiestaaと同じ問題が発生し
nltk関連のインポートと関数をコメントアウトした後、問題は解決しました。

詳細:
OS:ヨセミテ10.10.5
Python:2.7.10
ページコンテンツの取得:最初はurllib2を使用し、後でリクエストに切り替えました。

これは非常に深刻なバグであり、誰かが介入して修正できることを願っています。 ありがとう!

実稼働レベルのNLPを実行している場合、これは深刻な問題だと思います。 Rq(http://python-rq.org/)ワーカーを使用して、複数のNLPパイプラインを実行していますが、ネットワーク呼び出しを行うと、サイレントに強制終了されます。 すぐに修正されることを願っています。 ありがとう!

@sasinda :nltk-devメーリングリストに電話をかけて、この問題に注意を向けられるかどうかを確認することをお勧めします。

@sasinda Rqが正確にどのように機能するかはわかりませんが、本番レベルのNLPプロジェクトでは、シェルスクリプトを使用して起動時に各プロセスを生成し、分離された分離されたPythonインタープリターで各プロセスを開始することでこの問題を回避できました。 この場合、Pythonはフォークする必要がなく、nltkからのサイレントクラッシュは発生しません。 たぶん、これは当面は役立つでしょう。

関数レベルでインポートを実行すると、問題が回避されることがわかりました。

言い換えれば、これは機能します:

def split(words):
    import nltk
    return nltk.word_tokenize(words)

そしてこれはしません:

import nltk
def split(words):
    return nltk.word_tokenize(words)

@mpenkovに感謝します。 これで問題は解決しますか?

@stevenbirdそうは思いません。 これは回避策ですが、修正ではありません。

IMHO、サードパーティのライブラリをインポートするとPython標準ライブラリコンポーネントが壊れた場合、どこかで何か不幸なことが起こっているので、修正する必要があります。

@mpenkovなぜこれが機能するのか完全には@ oxymor0nの元のコードの変更:

from multiprocessing import Process
import nltk
import time
import urllib2

# HACK
urllib2.build_opener(urllib2.HTTPHandler())

def child_fn():
    print "Fetch URL"
    import urllib2
    print urllib2.urlopen("https://www.google.com").read()[:100]
    print "Done"


while True:
    child_process = Process(target=child_fn)
    child_process.start()
    child_process.join()
    print "Child process returned"
    time.sleep(1)

@mpenkov @ ninowalker@ oxymor0n @sasinda @wenbowangあなたはまだ同じ問題に直面していますか?

自分のマシンで問題を再現できませんでした:

from multiprocessing import Process
import nltk
import time

def child_fn():
    print "Fetch URL"
    import urllib2
    print urllib2.urlopen("https://www.google.com").read()[:100]
    print "Done"


while True:
    child_process = Process(target=child_fn)
    child_process.start()
    child_process.join()
    print "Child process returned"
    time.sleep(1)

私に与える:

Fetch URL
<!doctype html><html itemscope="" itemtype="http://schema.org/WebPage" lang="en-SG"><head><meta cont
Done
Child process returned
Fetch URL
<!doctype html><html itemscope="" itemtype="http://schema.org/WebPage" lang="en-SG"><head><meta cont
Done
Child process returned
Fetch URL
<!doctype html><html itemscope="" itemtype="http://schema.org/WebPage" lang="en-SG"><head><meta cont
Done

私は〜に乗っています:

  • Python 2.7.12
  • NLTK 3.2.5
  • Ubuntu 16.04.3

@alvationsこの問題を見つけてから久しぶりです。
どのプロジェクトベースでこの問題が発生しているのかさえ忘れていたので、まだ問題があるかどうかはわかりませんでした。
ごめんなさい!

@alvations私も、どのプロジェクトがこの特定の問題に苦しんでいたかを覚えていません。

自分のマシンでコードを実行しましたが、問題を再現できませんでした。

Python 2.7.12
nltk 3.2.1
macOS 10.12.6

@alvations私もそのプロジェクトに取り組んでいません。 ただし、これらの回避策の1つを使用しました。
私はあなたのコードを試しましたが、それでも子プロセスは私のためにセグメンテーション違反(終了コード11)で終了します(行:urllib2.urlopen( "https://www.google.com")。read()[:100]で終了します)

ただし、urllib3(https://urllib3.readthedocs.io/en/latest/)では機能しました。

  • nltk(3.2.5)
  • urllib3(1.22)
  • Mac OSX 10.12.16
  • Python 2.7.13 | Continuum Analytics、Inc。| (デフォルト、2016年12月20日、23:05:08)
    [GCC4.2.1互換性のあるAppleLLVM 6.0(clang-600.0.57)]ダーウィン

私の知る限り、この問題はmacOSに影響を及ぼしているようです。 これまでのところPython3.6を使用して、

  • macOS 10.13(失敗)
  • Centos 7.2(成功)
  • Ubuntu 16.04(成功)

python3用に変更されたOPのスクリプト:

from multiprocessing import Process
import nltk
import time


def child_fn():
    from urllib.request import urlopen
    print("Fetch URL")
    print(urlopen("https://www.google.com").read()[:100])
    print("Done")


child_process = Process(target=child_fn)
child_process.start()
child_process.join()
print("Child process returned")
time.sleep(1)

出力:

Fetch URL
Child process returned

サブプロセスは予期せず終了し、このStackOverflowの投稿に見られるものと同様の出力を受け取ります。

これはかなり気が遠くなるようなことだと思います。 MacOSでのスレッド処理と関係があるかもしれません。

私はnltkにあまり詳しくありませんが、テストの合格/不合格の原因を確認するために少しブラインドを突っ込みました。 テストに合格するために、パッケージ__init__.pyに対して行う必要があることは次のとおりです。


詳細(クリックして展開)

###########################################################
# TOP-LEVEL MODULES
###########################################################

# Import top-level functionality into top-level namespace

from nltk.collocations import *
from nltk.decorators import decorator, memoize
# from nltk.featstruct import *
# from nltk.grammar import *
from nltk.probability import *
from nltk.text import *
# from nltk.tree import *
from nltk.util import *
from nltk.jsontags import *

# ###########################################################
# # PACKAGES
# ###########################################################

# from nltk.chunk import *
# from nltk.classify import *
# from nltk.inference import *
from nltk.metrics import *
# from nltk.parse import *
# from nltk.tag import *
from nltk.tokenize import *
from nltk.translate import *
# from nltk.sem import *
# from nltk.stem import *

# Packages which can be lazily imported
# (a) we don't import *
# (b) they're slow to import or have run-time dependencies
#     that can safely fail at run time

from nltk import lazyimport
app = lazyimport.LazyModule('nltk.app', locals(), globals())
chat = lazyimport.LazyModule('nltk.chat', locals(), globals())
corpus = lazyimport.LazyModule('nltk.corpus', locals(), globals())
draw = lazyimport.LazyModule('nltk.draw', locals(), globals())
toolbox = lazyimport.LazyModule('nltk.toolbox', locals(), globals())

# Optional loading

try:
    import numpy
except ImportError:
    pass
else:
    from nltk import cluster

# from nltk.downloader import download, download_shell
# try:
#     from six.moves import tkinter
# except ImportError:
#     pass
# else:
#     try:
#         from nltk.downloader import download_gui
#     except RuntimeError as e:
#         import warnings
#         warnings.warn("Corpus downloader GUI not loaded "
#                       "(RuntimeError during import: %s)" % str(e))

# explicitly import all top-level modules (ensuring
# they override the same names inadvertently imported
# from a subpackage)

# from nltk import ccg, chunk, classify, collocations
# from nltk import data, featstruct, grammar, help, inference, metrics
# from nltk import misc, parse, probability, sem, stem, wsd
# from nltk import tag, tbl, text, tokenize, translate, tree, treetransforms, util


興味深いことに、無効にされたすべてのインポートは、最終的にtkinterインポートに戻ります。これが、根本的な原因だと思います。 テストスクリプトでimport nltkimport tkinterに置き換えると、非常によく似たクラッシュレポートが表示され、どちらもtkinterを参照しています。

私の知る限り、これらのパッケージはtkinter直接インポートします。

  • nltk.app
  • nltk.draw
  • nltk.sem

上記のメインパッケージ__init__への変更から、これらは問題のあるインポートであり、tkinterのインポートにどのようにさかのぼりますか

  • nltk.featstructsem
  • nltk.grammarfeatstruct
  • nltk.treegrammar
  • nltk.chunkchunk.named_entity > tree
  • nltk.parseparse.bllip > tree
  • nltk.tagtag.stanford > parse
  • nltk.classifyclassify.senna > tag
  • nltk.inferenceinference.discourse > semtag
  • nltk.stemstem.snowball > corpus > corpus.reader.timit > tree

@rpkilbyに感謝し

この問題のようですhttps://stackoverflow.com/questions/16745507/tkinter-how-to-use-threads-to-preventing-main-event-loop-from-freezing

ティンクターは私たちにとってかなり長い間悩みの種だったと思います。 おそらく、それに代わるものを見つけることができれば良いでしょう。

同意する。 短期的な解決策は、tkinterのインポートを、tkinterを必要とするクラスとメソッド内に埋め、それを必要としないプログラムによるインポートを回避することです。 numpyについても同様のことをすでに行っています。

このページは役に立ちましたか?
0 / 5 - 0 評価

関連する問題

libingnan54321 picture libingnan54321  ·  3コメント

ndvbd picture ndvbd  ·  4コメント

zdog234 picture zdog234  ·  3コメント

stevenbird picture stevenbird  ·  3コメント

alvations picture alvations  ·  4コメント