Python 子进程在发出 HTTP 请求时静默崩溃

Posted

技术标签:

【中文标题】Python 子进程在发出 HTTP 请求时静默崩溃【英文标题】:Python child process silently crashes when issuing an HTTP request 【发布时间】:2015-08-26 07:12:25 【问题描述】:

在组合多处理、请求(或 urllib2)和 nltk 时遇到问题。这是一个非常简单的代码:

>>> from multiprocessing import Process
>>> import requests
>>> from pprint import pprint
>>> Process(target=lambda: pprint(
        requests.get('https://api.github.com'))).start()
>>> <Response [200]>  # this is the response displayed by the call to `pprint`.

关于这段代码的更多细节:

    导入一些必需的模块 启动子进程 从子进程向“api.github.com”发出 HTTP GET 请求 显示结果

这很好用。导入nltk时出现问题:

>>> import nltk
>>> Process(target=lambda: pprint(
        requests.get('https://api.github.com'))).start()
>>> # nothing happens!

在导入 NLTK 之后,请求实际上默默地使线程崩溃(如果您尝试使用命名函数而不是 lambda 函数,在调用前后添加一些 print 语句,您会看到执行停止直接拨打requests.get) 有谁知道 NLTK 中的什么可以解释这种行为,以及如何克服这个问题?

这是我正在使用的版本:

$> python --version
Python 2.7.5
$> pip freeze | grep nltk
nltk==2.0.5
$> pip freeze | grep requests
requests==2.2.1

我正在运行 Mac OS X v. 10.9.5。

谢谢!

【问题讨论】:

问题与 SSL 无关,将 github api URL 替换为 'google.com' 不会改变导入/不导入 nltk 的行为。 这个问题也与requests无关。当用req = urllib2.Request('http://google.com'); handler = urllib2.urlopen(req); print handler.getcode() 替换对requests.get 的调用时,问题仍然存在。 将 nltk 升级到最新版本也没有解决问题... 尝试在没有多处理的情况下做同样的事情,即在同一个进程中执行它,看看会发生什么。 这可行,该问题特定于从子进程发送的请求。此错误已在 2 个月前报告:github.com/nltk/nltk/issues/947。但是,我正在运行的 NLTK 版本已于 2012 年 11 月发布,我很惊讶没有人更早注意到它。 【参考方案1】:

这个问题似乎还没有解决。 https://github.com/nltk/nltk/issues/947 我认为这是一个严重的问题(除非你在玩 NLTK,做 POC 并尝试模型,而不是实际的应用程序) 我正在 RQ 工作人员中运行 NLP 管道 (http://python-rq.org/)

nltk==3.2.1
requests==2.9.1

【讨论】:

如有需要,请提出新问题。这看起来像是评论,而不是实际问题的答案。 抱歉,这是一条评论。我仍然没有 50 声望来评论 :) @SasindaRukshan 您现在有足够的声望将其移至评论。【参考方案2】:

更新您的 python 库和 python 应该可以解决问题:

alvas@ubi:~$ pip freeze | grep nltk
nltk==3.0.3
alvas@ubi:~$ pip freeze | grep requests
requests==2.7.0
alvas@ubi:~$ python --version
Python 2.7.6
alvas@ubi:~$ lsb_release -a
No LSB modules are available.
Distributor ID: Ubuntu
Description:    Ubuntu 14.04.2 LTS
Release:    14.04
Codename:   trusty

来自代码:

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="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@ubi:~$ 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]>

它也应该适用于python3

alvas@ubi:~$ python3
Python 3.4.0 (default, Jun 19 2015, 14:20:21) 
[GCC 4.8.2] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> from multiprocessing import Process
>>> import requests
>>> Process(target=lambda: print(requests.get('https://api.github.com'))).start()
>>> 
>>> <Response [200]>

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

【讨论】:

【参考方案3】:

在子进程中使用 Nltk 和 Python 请求似乎很少见。尝试使用 Thread 而不是 Process,我遇到了与其他一些库和请求完全相同的问题,并且用 Thread 替换 Process 对我有用。

【讨论】:

以上是关于Python 子进程在发出 HTTP 请求时静默崩溃的主要内容,如果未能解决你的问题,请参考以下文章

从 python 子进程获取输出并向其发出命令

确保子进程在退出 Python 程序时死亡

python 啥是http异步请求

使用用户名和密码从反应应用程序静默登录到 auth0

监听主进程的 HTTP 流量,处理子进程的连接?

在 NestJS HTTP 服务器中使用子进程时,受 CPU 限制的进程会阻塞工作池