Python urlopen/requests.get在导入模块中创建的线程中不工作

Python urlopen/requests.get在导入模块中创建的线程中不工作,python,multithreading,python-requests,urllib2,urlopen,Python,Multithreading,Python Requests,Urllib2,Urlopen,我对urlopen有问题 (和请求。get) 在我的程序中,如果我在一个线程内运行它(我也用多处理进行了测试)[更新:一个由导入的模块创建的线程],它在程序结束之前不会运行 我所说的“不运行”是指甚至不启动:超时(这里是3秒)永远不会触发,并且没有与网站的连接 以下是我的简化代码: import threading,urllib2,time def dlfile(url): print 'Before request' r = urllib2.urlopen(url, timeout=

我对urlopen有问题 (和请求。get)

在我的程序中,如果我在一个线程内运行它(我也用
多处理
进行了测试)[更新:一个由导入的模块创建的线程],它在程序结束之前不会运行

我所说的“不运行”是指甚至不启动:超时(这里是3秒)永远不会触发,并且没有与网站的连接

以下是我的简化代码:

import threading,urllib2,time

def dlfile(url):
  print 'Before request'
  r = urllib2.urlopen(url, timeout=3)
  print 'After request'
  return r

def dlfiles(*urls):
  threads = [threading.Thread(None, dlfile, None, (url,), {}) for url in urls]
  map(lambda t:t.start(), threads)

def main():
    dlfiles('http://google.com')

main()
time.sleep(10)
print 'End of program'
我的输出:

Before request
End of program
After request
不幸的是,我正在编写的代码工作正常(即“请求前/请求后/程序结束”),我还不能用简化的代码重现这个问题

我仍在尝试,但与此同时,我想知道是否有人遇到过这种奇怪的行为,以及是什么导致了这种行为。请注意,如果我不使用线程,一切都很好

谢谢你能提供的帮助,我有点迷路了,连互联网都不知道

更新 下面是如何重现这种行为

threadtest.py

import threading,urllib2,time
def log(a):print(a)
def dlfile(url):
  log('Before request')
  r = urllib2.urlopen(url, timeout=3)
  log('After request')
  return r

def dlfiles(*urls):
  threads = [threading.Thread(None, dlfile, None, (url,), {}) for url in urls]
  map(lambda t:t.start(), threads)

def main():
    dlfiles('http://google.com')

main()
for i in range(5):
    time.sleep(1)
    log('Sleep')
log('End of program')
threadtest导入.py

import threading,urllib2,time
def log(a):print(a)
def dlfile(url):
  log('Before request')
  r = urllib2.urlopen(url, timeout=3)
  log('After request')
  return r

def dlfiles(*urls):
  threads = [threading.Thread(None, dlfile, None, (url,), {}) for url in urls]
  map(lambda t:t.start(), threads)

def main():
    dlfiles('http://google.com')

main()
for i in range(5):
    time.sleep(1)
    log('Sleep')
log('End of program')
导入线程测试

然后输出将如下所示:

$ python threadtest.py
Before request
After request
Sleep
Sleep
Sleep
Sleep
Sleep
End of program

$ python threadtest-import.py
Before request
Sleep
Sleep
Sleep
Sleep
Sleep
End of program
After request
现在我发现了如何繁殖:这种行为正常吗?期待


我怎样才能摆脱它呢?也就是说,从导入的模块创建一个线程,该线程可以按预期加载urlopen。

您的代码很好。预计单次发射

def main():
    dlfiles('http://google.fr')
这里您正在传递单个
url

threads = [threading.Thread(None, dlfile, None, (url,), {}) for url in urls]
列表理解将只产生一个线程,因为
URL
中只有一个元素

尝试:

def main():
    dlfiles('http://google.fr', 'http://google.com', 'http://google.gg')

感谢@user3351750的评论,我忘记发布解决方案了

问题是文件的结构。在threadtest-import.py中,我导入了threadtest,在导入模块的过程中,一些*(我不记得确切的机制)变成了阻塞。IIRC这与urllib中的re模块有关。 抱歉说不清楚

修复方法是将代码放入函数中导入的模块中。我想这是一个很好的做法

即,这样做:

import threadtest #do nothing except declarations
threadtest.run() #do the work
与此相反:

import threadtest #declarations + work
然后把密码

main()
for i in range(5):
    time.sleep(1)
    log('Sleep')
log('End of program')
运行
功能中:

def run():
    main()
    for i in range(5):
        time.sleep(1)
        log('Sleep')
    log('End of program')

这样,东西*就不再阻塞,一切正常。

也许我不够清楚,但我在OP中编写的代码只是一个简化的代码,甚至不会重现错误。我的问题是,在我的实际程序中,所有urlopen调用(1个或多个)都将仅在程序退出后进行。从今天起,
threadtest import.py
脚本将给出正常结果“请求前/请求后/睡眠*5”。我不明白这里发生了什么……我面临着类似的问题。你能找出原因吗?有解决办法吗?
def main():
    dlfiles('http://google.fr')