0

又是我的一个问题..又遇到了一些问题。希望能找到一个更聪明并且知道这一点的人.. :D

我现在遇到线程问题,当打开 (1,1000) 范围内的线程 url 时,我很想看到所有不同的 url。只有当我运行代码时,我才会得到很多双变量(可能是因为爬行速度如此之快)。无论如何,这是我的代码:我尝试查看它在哪个线程,但我得到了双打。

import threading
import urllib2
import time
import collections

results2 = []
def crawl():
    var_Number = thread.getName().split("-")[1]
    try:
        data = urllib2.urlopen("http://www.waarmaarraar.nl").read()
        results2.append(var_Number)
    except:
        crawl()

threads = []

for n in xrange(1, 1000):
    thread = threading.Thread(target=crawl)
    thread.start()  
    threads.append(thread)

# to wait until all three functions are finished
print "Waiting..."

for thread in threads:
    thread.join()

print "Complete."

# print results (All numbers, should be 1/1000)
results2.sort()
print results2    
# print doubles (should be [])
print [x for x, y in collections.Counter(results2).items() if y > 1]

但是,如果我直接在 xrange 行下添加 time.sleep(0.1),则不会出现这些双打。尽管这确实使我的程序减慢了很多。任何人都知道解决此问题的更好方法吗?

4

2 回答 2

0

根据Thread.getName()上的文档,这是正确的行为。

如果您想为每个线程设置一个唯一的名称,您必须使用name 属性来设置它。

根据您最终的期望,替换

for n in xrange(1, 1000):
    thread = threading.Thread(target=crawl)
    thread.start()  
    threads.append(thread)

for n in xrange(1, 1000):
    thread = threading.Thread(target=crawl)
    thread.name = n
    thread.start()  
    threads.append(thread)

并且应该var_Number = thread.getName().split("-")[1]可以var_Number = thread.name帮助您。

编辑
经过一些测试后,用户自定义名称可以被另一个线程重用,因此唯一通过的方法n是使用argsor kwargsof threading.Thread()
这种行为是有道理的,如果我们需要在线程中使用某种数据,正确传递它不要试图把它放在不属于它的地方。

于 2012-10-09T21:59:50.730 回答
0

异常处理程序中有一个递归调用crawl()。如果出现错误,同一个线程会多次运行该函数。因此results2可能包含相同的var_Number几次。如果添加time.sleep(.1)(暂停);您的脚本消耗更少的资源,例如打开的 fds 的数量、正在运行的线程以及对远程服务器的请求更有可能成功。

默认线程名称也可能重复。如果线程退出;另一个线程可能具有相同的名称,例如,如果实现使用.ident属性来生成名称。

笔记:

  • 使用pep-8 命名约定。您可以使用 pep8、pyflakes、epylint 命令行工具自动检查您的代码
  • 您不需要 1000 个线程来获取 1000 个网址(请参阅我对您上一个问题的评论
  • 在同一个站点没有暂停的情况下生成请求并不好。
于 2012-10-09T22:06:37.467 回答