Honnêtement, ce problème n'est pas aussi grave que curieux. J'ai découvert que lorsque NLTK est importé, tout sous-processus Python se terminera prématurément sur un appel réseau. Exemple de code:
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)
Exécutez-le avec NLTK importé, et vous verrez que l'appel urlopen () n'est jamais exécuté. Commentez la ligne import nltk
, et elle s'exécute correctement.
Pourquoi?
* edit: c'est pour Python 2. Je ne l'ai pas encore testé sur 3.
Avez-vous des exceptions?
non. J'ai mis une clause try .. except:
autour du import urllib2; print...
mais je n'en ai rien tiré.
Je rencontre exactement le même problème. Je viens d'ouvrir une question SO qui peut être utile pour être liée ici: http://stackoverflow.com/questions/30766419/python-child-process-silently-crashes-when-issuing-an-http-request
Le processus enfant plante en effet silencieusement sans autre préavis.
Je ne suis pas d'accord avec vous @ oxymor0n , cela
The child process is indeed crashing silently without further notice.
Nous rencontrons également ce problème avec la combinaison de: nltk, gunicorn (avec nltk chargé via prefork) et flask.
Supprimez l'importation nltk et tout fonctionne. Sauf nltk.
/ cc @escherba
@ninowalker , @ oxymor0n C'est étrange, mes processus fonctionnent bien avec le code, j'obtiens:
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
C'est le résultat attendu, non?
Cela ne rompt pas ma demande avec ceci aussi:
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]>
J'utilise:
J'ai rencontré le même problème que @Hiestaa . J'ai un fichier d'aide string_util.python qui importe nltk, mais il n'est pas utilisé dans le fichier python principal qui utilise le module multitraitement pour démarrer un robot d'exploration multi-processus. Le symptôme est que le processus enfant est bloqué et il n'y a pas de message d'erreur (pas même de message d'exception).
Après avoir commenté les importations et les fonctions liées à nltk, le problème a été résolu.
Détails:
Système d'exploitation: Yosemite 10.10.5
Python: 2.7.10
Récupérer le contenu de la page: j'ai utilisé urllib2 au départ, puis je suis passé aux requêtes plus tard.
C'est un bug très sérieux, et j'espère que quelqu'un pourra intervenir et le corriger. Merci!
Je pense que c'est un problème sérieux si vous faites de la PNL de niveau de production. Nous utilisons des workers Rq (http://python-rq.org/), pour exécuter plusieurs pipelines NLP, qui sont tués silencieusement lors d'appels réseau. J'espère qu'il y aura bientôt un correctif. Merci!
@sasinda : Vous voudrez peut-être lancer un appel sur la liste de diffusion nltk-dev pour voir si vous pouvez attirer l'attention sur ce problème.
@sasinda Je ne sais pas comment Rq fonctionne exactement mais dans mon projet PNL de niveau production, j'ai réussi à contourner ce problème en démarrant chaque processus dans un interpréteur python séparé et isolé, en utilisant un script shell pour les générer au démarrage. Dans ce cas, python n'a jamais besoin de fork et le crash silencieux de nltk ne se produit jamais. Peut-être que cela peut aider en attendant.
J'ai constaté que l'exécution de l'importation au niveau de la fonction évite le problème.
En d'autres termes, cela fonctionne:
def split(words):
import nltk
return nltk.word_tokenize(words)
et ce n'est pas:
import nltk
def split(words):
return nltk.word_tokenize(words)
Merci @mpenkov. Cela résout-il le problème?
@stevenbird, je ne pense pas. C'est une solution de contournement, mais ce n'est pas une solution.
IMHO, si l'importation d'une bibliothèque tierce casse un composant de bibliothèque standard Python, quelque chose d'impie se produit quelque part et doit être corrigé.
@mpenkov Je ne suis pas tout à fait sûr de savoir pourquoi cela fonctionne, mais voici une autre solution de contournement que j'ai trouvée. Construire un ouvreur dans le processus parent semble résoudre ce problème. Modification du code original de @ 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 Êtes-vous tous confrontés au même problème?
Je n'ai pas pu reproduire le problème sur ma machine:
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)
Donne moi:
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
Je suis dessus:
@alvations Cela fait longtemps que je n'ai pas trouvé ce problème.
J'ai même oublié quelle base de projet avait ce problème, donc je ne pourrais pas vous dire si j'ai toujours le problème ou non.
Pardon!
@alvations Je ne me souviens pas non plus lequel de mes projets a souffert de ces problèmes spécifiques.
J'ai exécuté votre code sur ma machine et je n'ai pas pu reproduire le problème.
Python 2.7.12
nltk 3.2.1
macOS 10.12.6
@alvations Moi aussi, je ne travaille plus sur ce projet. Mais utilisé l'une de ces solutions de contournement.
J'ai essayé votre code mais le processus enfant se termine toujours avec une erreur de segment (code de sortie 11) pour moi (quitte à la ligne: urllib2.urlopen ("https://www.google.com") .read () [: 100])
Cela fonctionnait avec urllib3 (https://urllib3.readthedocs.io/en/latest/).
Pour autant que je sache, ce problème semble affecter macOS. En utilisant Python 3.6 jusqu'à présent,
Script d'OP modifié pour 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)
Production:
Fetch URL
Child process returned
Le sous-processus se ferme de manière inattendue, recevant une sortie similaire à ce qui est vu dans cette publication Stack Overflow .
Je pense que c'est assez époustouflant. Cela pourrait avoir quelque chose à voir avec la gestion des threads sur MacOS.
Je ne suis pas très familier avec nltk, mais j'ai fouillé un peu à l'aveugle pour voir ce qui a fait passer le test / échouer. Voici ce que j'ai dû faire avec le package __init__.py
pour que le test réussisse:
Détails (cliquez pour agrandir)
###########################################################
# 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
Fait intéressant, toutes les importations désactivées conduisent finalement à l'importation de tkinter
, ce qui, je pense, en est la cause première. Si je remplace import nltk
par import tkinter
dans le script de test, j'obtiens un rapport d'erreur très similaire, tous deux faisant référence à tkinter.
D'après ce que je peux dire, ces packages importent directement tkinter
:
nltk.app
nltk.draw
nltk.sem
À partir des modifications ci-dessus apportées au package principal __init__
, voici les importations problématiques, et comment elles remontent à l'importation de 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
)Merci @rpkilby , c'est très utile!
Cela ressemble à ce problème https://stackoverflow.com/questions/16745507/tkinter-how-to-use-threads-to-preventing-main-event-loop-from-freezing
Je pense que le bricolage est un problème pour nous depuis un certain temps. Peut-être que ce sera bien si nous pouvons trouver une alternative.
Je suis d'accord. Une solution à plus court terme serait d'enterrer les importations tkinter dans les classes et les méthodes qui ont besoin de tkinter, et d'éviter de l'importer par des programmes qui n'en ont pas besoin. Nous avons déjà fait quelque chose de similaire pour numpy.
Commentaire le plus utile
Je ne suis pas très familier avec nltk, mais j'ai fouillé un peu à l'aveugle pour voir ce qui a fait passer le test / échouer. Voici ce que j'ai dû faire avec le package
__init__.py
pour que le test réussisse:Détails (cliquez pour agrandir)
Fait intéressant, toutes les importations désactivées conduisent finalement à l'importation de
tkinter
, ce qui, je pense, en est la cause première. Si je remplaceimport nltk
parimport tkinter
dans le script de test, j'obtiens un rapport d'erreur très similaire, tous deux faisant référence à tkinter.D'après ce que je peux dire, ces packages importent directement
tkinter
:nltk.app
nltk.draw
nltk.sem
À partir des modifications ci-dessus apportées au package principal
__init__
, voici les importations problématiques, et comment elles remontent à l'importation de tkinternltk.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
)