0

请原谅无用的变量名和不必要的臃肿代码,但我只是迅速将它们拼凑在一起,还没有时间优化或整理。

我编写了这个程序,通过解析 URL 的消息日志,转储我和朋友使用网络摄像头照片共享服务 (321cheese.com) 相互发送的所有图像。问题是我的多线程似乎不起作用。

在我的代码底部,您会看到我的注释掉的非多线程下载方法,它始终产生正确的结果(在本例中为 121 张照片)。但是当我尝试将此动作发送到新线程时,程序有时会下载 112 张照片,有时会下载 90 张照片,有时会下载 115 张照片等,但从未给出正确的结果。

为什么这会产生问题?我应该限制同时线程的数量(以及如何)?

import urllib
import thread

def getName(input):
    l = input.split(".com/")
    m = l[1]
    return m

def parseMessages():
    theFile = open('messages.html', 'r')
    theLines = theFile.readlines()
    theFile.close()
    theNewFile = open('new321.txt','w')
    for z in theLines:
        if "321cheese" in z:
            theNewFile.write(z)
    theNewFile.close()

def downloadImage(inputURL):
    urllib.urlretrieve (inputURL, "./grabNew/" + d)

parseMessages()

f = open('new321.txt', 'r')
lines = f.readlines()
f.close()

g = open('output.txt', 'w')

for x in lines:
  a = x.split("<a href=\"")
  b = a[1].split("\"")
  c = b[0]
  if ".png" in c:
    d = getName(c)
    g.write(c+"\n")
    thread.start_new_thread( downloadImage, (c,) )
    ##downloadImage(c)

g.close()
4

2 回答 2

1

您的代码中有多个问题。

主要问题是d多个线程中的全局名称使用。要修复它,请将名称作为参数显式传递给downloadImage().

限制并发下载数量的简单方法(代码方面)是使用concurrent.futures(在 Python 2 上可用futures)或multiprocessing.Pool

#!/usr/bin/env python
import urllib
from multiprocessing import Pool
from posixpath import basename
from urllib import unquote
from urlparse import urlsplit


download_dir = "grabNew"

def url2filename(url):
    return basename(unquote(urlsplit(url).path).decode('utf-8'))

def download_image(url):
    filename = None
    try:
        filename = os.path.join(download_dir, url2filename(url))
        return urllib.urlretrieve(url, filename), None
    except Exception as e:
        return (filename, None), e

def main():
    pool = Pool(processes=10)
    for (filename, headers), error in pool.imap_unordered(download_image, get_urls()):
        pass # do something with the downloaded file or handle an error

if __name__ == "__main__":
   main()
于 2012-12-03T01:43:52.123 回答
1

你确定你的解析工作正常吗?

此外,您正在启动太多线程。

最后...... python 中的线程是假的!如果您想要真正的并行性,请使用多处理模块,但由于图像可能都来自同一服务器,如果您同时打开一百个与同一服务器的连接,它的防火墙可能会开始丢弃您的连接。

于 2012-12-03T00:05:14.250 回答