Nltk: multiprocessing dan nltk tidak bekerja sama dengan baik

Dibuat pada 16 Apr 2015  ·  22Komentar  ·  Sumber: nltk/nltk

Sejujurnya, masalah ini tidak seserius yang membuat penasaran. Saya telah menemukan bahwa ketika NLTK diimpor, itu akan menyebabkan subproses Python apa pun berhenti sebelum waktunya pada panggilan jaringan. Kode contoh:

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)

Jalankan dengan impor NLTK, dan Anda akan melihat bahwa panggilan urlopen () tidak pernah dijalankan. Komentari baris import nltk , dan itu berjalan dengan baik.

Mengapa?

* edit: ini untuk Python 2. Saya belum mengujinya di 3.

admin bug inactive multithread / multiprocessing pythonic

Komentar yang paling membantu

Saya tidak terlalu familiar dengan nltk, tapi saya sedikit mengotak-atik untuk melihat apa yang menyebabkan tes lulus / gagal. Inilah yang harus saya lakukan pada paket __init__.py agar tes lulus:


Detail (klik untuk memperluas)

###########################################################
# 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


Menariknya, semua impor yang dinonaktifkan pada akhirnya mengarah kembali ke impor tkinter , yang menurut saya adalah akar masalahnya. Jika saya mengganti import nltk dengan import tkinter dalam skrip pengujian, saya mendapatkan laporan kerusakan yang sangat mirip, keduanya mereferensikan tkinter.

Dari apa yang saya tahu, paket-paket ini langsung mengimpor tkinter :

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

Dari perubahan di atas ke paket utama __init__ , ini adalah impor bermasalah, dan bagaimana mereka menelusuri kembali ke pengimporan tkinter

  • nltk.featstruct ( sem )
  • nltk.grammar ( featstruct )
  • nltk.tree ( grammar )
  • nltk.chunk ( chunk.named_entity > tree )
  • nltk.parse ( parse.bllip > tree )
  • nltk.tag ( tag.stanford > parse )
  • nltk.classify ( classify.senna > tag )
  • nltk.inference ( inference.discourse > sem , tag )
  • nltk.stem ( stem.snowball > corpus > corpus.reader.timit > tree )

Semua 22 komentar

Apakah Anda mendapatkan pengecualian?

tidak. saya meletakkan klausa try .. except: sekitar import urllib2; print... tetapi tidak mendapat apa-apa darinya.

Saya mengalami masalah yang sama persis. Saya baru saja membuka pertanyaan SO yang mungkin berguna untuk ditautkan di sini: http://stackoverflow.com/questions/30766419/python-child-process-silently-crashes-when-issuing-an-http-request

Proses anak ini memang berjalan diam-diam tanpa pemberitahuan lebih lanjut.

Saya tidak setuju dengan Anda @ oxymor0n , ini tampaknya masalah yang cukup serius bagi saya. Ini pada dasarnya berarti bahwa setiap kali nltk diimpor, tidak ada cara untuk mengeluarkan permintaan dari proses anak yang bisa sangat mengganggu saat bekerja dengan API.

The child process is indeed crashing silently without further notice.

Kami juga mengalami masalah ini dengan kombinasi dari: nltk, gunicorn (dengan nltk dimuat melalui prefork), dan flask.

Hapus impor nltk, dan semuanya bekerja. Kecuali nltk.

/ cc @escherba

@ninowalker , @ oxymor0n Aneh, proses saya berjalan dengan baik dengan kode, saya mendapatkan:

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

Itu hasil yang diharapkan, bukan?

Itu juga tidak merusak permintaan saya dengan ini:

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]>

Saya menggunakan:

  • python 2.7.6
  • nltk 3.0.3
  • ubuntu 14.04

Saya mengalami masalah yang sama dengan @Hiestaa . Saya memiliki file helper string_util.python yang mengimpor nltk, tetapi tidak digunakan dalam file python utama yang menggunakan modul multiprosesing untuk memulai crawler multi-proses. Gejalanya adalah proses anak hanya macet dan tidak ada pesan kesalahan (bahkan pesan pengecualian).
Setelah mengomentari impor dan fungsi terkait nltk, masalah tersebut teratasi.

Rincian:
OS: Yosemite 10.10.5
Python: 2.7.10
Ambil konten halaman: Saya menggunakan urllib2 pada awalnya, kemudian beralih ke permintaan nanti.

Ini adalah bug yang sangat serius, dan saya harap seseorang dapat turun tangan dan memperbaikinya. Terima kasih!

Saya pikir ini adalah masalah serius jika Anda melakukan NLP tingkat produksi. Kami menggunakan pekerja Rq (http://python-rq.org/), untuk menjalankan beberapa pipeline NLP, yang akan mati secara diam-diam saat melakukan panggilan jaringan. Semoga segera ada perbaikan. Terima kasih!

@sasinda : Anda mungkin ingin menghubungi milis nltk-dev untuk mengetahui apakah Anda dapat memperhatikan masalah ini.

@sasinda Saya tidak yakin bagaimana Rq bekerja dengan tepat tetapi dalam proyek NLP tingkat produksi saya, saya berhasil mengatasi masalah ini dengan memulai setiap proses dalam interpreter python yang terpisah dan terisolasi, menggunakan skrip shell untuk menelurkannya saat start-up. Dalam hal ini python tidak pernah harus bercabang dan crash diam-diam dari nltk tidak pernah terjadi. Mungkin ini bisa membantu sementara itu.

Saya telah menemukan bahwa melakukan impor pada tingkat fungsi menghindari masalah.

Dengan kata lain, ini berhasil:

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

dan ini tidak:

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

Terima kasih @mpenkov. Apakah ini menyelesaikan masalah?

@stevenbird Saya rasa tidak. Ini solusi, tapi itu bukan perbaikan.

IMHO, jika mengimpor pustaka pihak ketiga merusak komponen pustaka standar Python, sesuatu yang tidak suci terjadi di suatu tempat, dan perlu diperbaiki.

@mpenkov Saya tidak sepenuhnya yakin mengapa ini berhasil, tapi inilah solusi lain yang saya temukan berhasil. Membangun pembuka dalam proses induk tampaknya memperbaikinya. Memodifikasi kode asli @ 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 Apakah Anda semua masih menghadapi masalah yang sama?

Saya tidak dapat mereplikasi masalah di komputer saya:

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)

beri saya:

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

Aku di:

  • Python 2.7.12
  • NLTK 3.2.5
  • Ubuntu 16.04.3

@alvations Sudah lama sekali saya tidak menemukan masalah ini.
Saya bahkan lupa basis proyek mana yang mengalami masalah ini, jadi saya tidak dapat memberi tahu Anda apakah saya masih mengalami masalah atau tidak.
Maaf!

@alvations Saya juga tidak ingat proyek mana yang mengalami masalah khusus ini.

Saya menjalankan kode Anda di komputer saya dan tidak dapat mereplikasi masalah.

Python 2.7.12
nltk 3.2.1
macOS 10.12.6

@alvations Saya juga tidak mengerjakan proyek itu lagi. Tetapi menggunakan salah satu solusi itu.
Saya mencoba kode Anda tetapi masih proses anak keluar dengan kesalahan segmen (kode keluar 11) untuk saya (keluar di baris: urllib2.urlopen ("https://www.google.com") .read () [: 100])

Ini bekerja dengan 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. | (default, 20 Des 2016, 23:05:08)
    [GCC 4.2.1 Kompatibel dengan Apple LLVM 6.0 (clang-600.0.57)] di darwin

Sejauh yang saya tahu, masalah ini tampaknya memengaruhi macOS. Menggunakan Python 3.6 sejauh ini,

  • macOS 10.13 (gagal)
  • Centos 7.2 (berhasil)
  • Ubuntu 16.04 (berhasil)

Skrip OP yang dimodifikasi untuk python3:

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)

Keluaran:

Fetch URL
Child process returned

Subproses berhenti tiba-tiba, menerima keluaran yang serupa dengan apa yang terlihat di pos Stack Overflow ini .

Saya pikir ini cukup membingungkan. Ini mungkin ada hubungannya dengan penanganan utas di MacOS.

Saya tidak terlalu familiar dengan nltk, tapi saya sedikit mengotak-atik untuk melihat apa yang menyebabkan tes lulus / gagal. Inilah yang harus saya lakukan pada paket __init__.py agar tes lulus:


Detail (klik untuk memperluas)

###########################################################
# 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


Menariknya, semua impor yang dinonaktifkan pada akhirnya mengarah kembali ke impor tkinter , yang menurut saya adalah akar masalahnya. Jika saya mengganti import nltk dengan import tkinter dalam skrip pengujian, saya mendapatkan laporan kerusakan yang sangat mirip, keduanya mereferensikan tkinter.

Dari apa yang saya tahu, paket-paket ini langsung mengimpor tkinter :

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

Dari perubahan di atas ke paket utama __init__ , ini adalah impor bermasalah, dan bagaimana mereka menelusuri kembali ke pengimporan tkinter

  • nltk.featstruct ( sem )
  • nltk.grammar ( featstruct )
  • nltk.tree ( grammar )
  • nltk.chunk ( chunk.named_entity > tree )
  • nltk.parse ( parse.bllip > tree )
  • nltk.tag ( tag.stanford > parse )
  • nltk.classify ( classify.senna > tag )
  • nltk.inference ( inference.discourse > sem , tag )
  • nltk.stem ( stem.snowball > corpus > corpus.reader.timit > tree )

Terima kasih @rpkilby , itu sangat membantu!

Sepertinya masalah ini https://stackoverflow.com/questions/16745507/tkinter-how-to-use-threads-to-preventing-main-event-loop-from-freezing

Saya pikir tinkter telah menjadi titik sakit bagi kami untuk beberapa waktu. Mungkin, akan lebih baik jika kita dapat menemukan alternatifnya.

Saya setuju. Solusi jangka pendek adalah mengubur impor tkinter di dalam kelas dan metode yang membutuhkan tkinter, dan menghindari mengimpornya oleh program yang tidak membutuhkannya. Kami telah melakukan sesuatu yang serupa untuk numpy.

Apakah halaman ini membantu?
0 / 5 - 0 peringkat

Masalah terkait

Chris00 picture Chris00  ·  3Komentar

vezeli picture vezeli  ·  3Komentar

libingnan54321 picture libingnan54321  ·  3Komentar

goodmami picture goodmami  ·  4Komentar

stevenbird picture stevenbird  ·  3Komentar