Честно говоря, это не столько серьезный вопрос, сколько любопытный. Я обнаружил, что когда 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
, и она будет выполнена нормально.
Зачем?
* изменить: это для Python 2. Я еще не тестировал его на 3.
Есть ли исключения?
нет. Я поместил предложение try .. except:
вокруг import urllib2; print...
но ничего от него не получил.
Я столкнулся с той же проблемой. Я только что открыл вопрос SO, который может быть полезен для ссылки здесь: http://stackoverflow.com/questions/30766419/python-child-process-silently-crashes-when-issuing-an-http-request
Дочерний процесс действительно тихо падает без дополнительного уведомления.
Я не согласен с вами @ oxymor0n ,
The child process is indeed crashing silently without further notice.
Мы также сталкиваемся с этой проблемой с комбинацией: nltk, gunicorn (с nltk, загруженным через prefork) и flask.
Удалите импорт 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]>
Я использую:
Я столкнулся с той же проблемой, что и @Hiestaa . У меня есть вспомогательный файл string_util.python, который импортирует nltk, но он не используется в основном файле python, который использует модуль многопроцессорности для запуска многопроцессорного поискового робота. Симптомом является то, что дочерний процесс просто застревает и нет сообщения об ошибке (даже сообщения об исключении).
После комментирования импорта и функций, связанных с nltk, проблема была решена.
Подробности:
ОС: Yosemite 10.10.5
Python: 2.7.10
Получение содержимого страницы: сначала я использовал urllib2, а потом переключился на запросы.
Это очень серьезная ошибка, и я надеюсь, что кто-нибудь сможет ее исправить. Спасибо!
Я думаю, что это серьезная проблема, если вы занимаетесь НЛП производственного уровня. Мы используем воркеры 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 Я так не думаю. Это обходной путь, но не исправление.
ИМХО, если импорт сторонней библиотеки ломает компонент стандартной библиотеки 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
Я на:
@alvations Я давно не обнаружил эту проблему.
Я даже забыл, в какой базе проекта возникла эта проблема, поэтому я не мог сказать вам, есть ли у меня проблема или нет.
Сожалею!
@alvations Я тоже не помню, какие из моих проектов страдали именно от этой проблемы.
Я запустил ваш код на своей машине и не смог воспроизвести проблему.
Python 2.7.12
nltk 3.2.1
macOS 10.12.6
@alvations Я тоже больше не работаю над этим проектом. Но использовал один из этих обходных путей.
Я пробовал ваш код, но все же дочерний процесс для меня завершился с ошибкой сегмента (код выхода 11) (выходит на строке: urllib2.urlopen ("https://www.google.com") .read () [: 100])
Однако он работал с urllib3 (https://urllib3.readthedocs.io/en/latest/).
Насколько я могу судить, эта проблема, похоже, затрагивает macOS. Пока использовал Python 3.6,
Измененный скрипт OP для 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)
Вывод:
Fetch URL
Child process returned
Подпроцесс неожиданно завершает работу, получая вывод, аналогичный тому, что мы видели в этой публикации о переполнении стека .
Я думаю, что это ошеломляет. Это может иметь какое-то отношение к обработке потоков в 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 nltk
на import tkinter
в тестовом скрипте, я получу очень похожий отчет о сбое, оба ссылаются на tkinter.
Насколько я могу судить, эти пакеты напрямую импортируют tkinter
:
nltk.app
nltk.draw
nltk.sem
Из приведенных выше изменений в основном пакете __init__
, это проблемный импорт и то, как они прослеживаются до импорта 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
)Спасибо @rpkilby , это очень полезно!
Похоже, эта проблема https://stackoverflow.com/questions/16745507/tkinter-how-to-use-threads-to-preventing-main-event-loop-from-freezing
Я думаю, что тинктер уже довольно давно является для нас проблемой. Возможно, будет хорошо, если мы найдем ему альтернативу.
Я согласен. Более краткосрочным решением было бы похоронить импорт tkinter внутри классов и методов, которым требуется tkinter, и избежать его импорта программами, которым он не нужен. Мы уже сделали нечто подобное для numpy.
Самый полезный комментарий
Я не очень хорошо знаком с nltk, но я немного покопался, чтобы увидеть, что заставило тест пройти / не пройти. Вот что мне нужно было сделать с пакетом
__init__.py
, чтобы пройти тест:Подробности (нажмите, чтобы развернуть)
Интересно, что весь отключенный импорт в конечном итоге приводит к импорту
tkinter
, что, как я думаю, является основной причиной. Если я заменюimport nltk
наimport tkinter
в тестовом скрипте, я получу очень похожий отчет о сбое, оба ссылаются на tkinter.Насколько я могу судить, эти пакеты напрямую импортируют
tkinter
:nltk.app
nltk.draw
nltk.sem
Из приведенных выше изменений в основном пакете
__init__
, это проблемный импорт и то, как они прослеживаются до импорта 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
)