【问题标题】:How to create and start any number of threads in python 3如何在 python 3 中创建和启动任意数量的线程
【发布时间】:2019-07-09 13:25:44
【问题描述】:

我正在制作一个从网页下载图像的脚本,并且我正在尝试使其成为多线程的,因此速度要快得多。

在下载功能中,我必须设置两个参数,因为当我设置一个(队列)时,我得到了这个错误:

TypeError: downloading() takes 1 positional arguments but 21* were given

** queue has 21 links

代码:

count = 0
queue = {"some urls", , , }
done = set()
path = 'foldername'


def downloading(queue, name):
    for imgs in queue:
        if imgs not in done:
            done.add(imgs)
            urllib.request.urlretrieve(imgs, path + '/' + imgs.split('/')[-1])
            global count
            count += 1
            print(str(count) + ' ' + name)
            print('Done:  ' + imgs.split('/')[-1])


def threads(queue):
    print('Start Downloading ...')
    th1 = Thread(target=downloading, args=(queue, "Thread 1"))
    th1.start()
    th2 = Thread(target=downloading, args=(queue, "Thread 2"))
    th2.start()
    th3 = Thread(target=downloading, args=(queue, "Thread 3"))
    th3.start()
    th4 = Thread(target=downloading, args=(queue, "Thread 4"))
    th4.start()
    th5 = Thread(target=downloading, args=(queue, "Thread 5"))
    th5.start()
    th6 = Thread(target=downloading, args=(queue, "Thread 6"))
    th6.start()
    th7 = Thread(target=downloading, args=(queue, "Thread 7"))
    th7.start()
    th8 = Thread(target=downloading, args=(queue, "Thread 8"))
    th8.start()
    th9 = Thread(target=downloading, args=(queue, "Thread 9"))
    th9.start()
    th10 = Thread(target=downloading, args=(queue, "Thread 10"))
    th10.start()

【问题讨论】:

  • 您可以使用for-loop 创建所有线程并将它们保留在列表中th[1].start()
  • 你确定你没有使用args=queue 吗?或args=queue, "Thread 1" 没有()
  • @furas 以及如何制作这个 for-loop ?我使用了args=queueargs=(queue) 两者都是一样的,我认为集合是这里的问题,就像它把每个元素作为一个参数而不是一个集合一样。 Traceback (most recent call last): File "C:\Users\nulla\AppData\Local\Programs\Python\Python37-32\lib\threading.py", line 917, in _bootstrap_inner self.run() File "C:\Users\nulla\AppData\Local\Programs\Python\Python37-32\lib\threading.py", line 865, in run self._target(*self._args, **self._kwargs) TypeError: downloading() takes 1 positional argument but 21 were given
  • @furas 没关系,我只是想通了,我不知道我应该把, 放在争论之后。让我们回到for-loop
  • 您运行相同的代码 10 次 - 您可以创建列表 all_threads = [ ] 并使用 for x in range(10): 运行 t = Thread(...) t.start()、all_threas.append(t)。这样您的代码更少,您可以更改range(10) 以运行更多线程。但是更多的线程并不一定意味着更快。 Python 使用 GIL 阻止线程并且它们不会同时运行。最好使用可以同时下载的ThreadPool或者grequests

标签: python python-3.x multithreading loops for-loop


【解决方案1】:

对所需的线程数使用简单的for 循环。当然,您应该以某种方式将它们保存到最后可能join它们:

def threads(queue):
    num_of_threads = 10
    print('Start Downloading ...')
    threads = []
    for i in range(1, num_of_threads+1):
        th = Thread(target=downloading, args=(queue, "Thread {}".format(i)))
        threads.append(th)
        th.start()
    return threads

正如建议的那样,pool 在这个用例中会很有帮助,因为它会优化您系统的运行:

from multiprocessing.dummy import Pool as ThreadPool

def downloading(img):
    urllib.request.urlretrieve(img, path + '/' + img.split('/')[-1])
    global count
    count += 1
    print('Done:  ' + img.split('/')[-1])

def threads(queue):
    pool = ThreadPool()
    pool.map(downloading, queue)
    pool.close()
    pool.join()

请注意,通过这种方式,您应该更改downloading 函数以接收一个作为单个图像的参数。 map 函数将可迭代项(第二个参数)的每个项目发送到一个函数(第一个参数)。这也是为什么不需要设置done 的原因,因为每张图像都会被处理一次。

【讨论】:

  • 谢谢,第一个代码正在运行,但我测试了second one,我得到了这个error
  • 嗨@albaraamarwan,我无法打开这些链接。你能解释一下出了什么问题吗?
猜你喜欢
  • 1970-01-01
  • 2013-05-31
  • 1970-01-01
  • 1970-01-01
  • 2016-10-11
  • 1970-01-01
  • 2013-01-03
  • 1970-01-01
  • 2016-03-21
相关资源
最近更新 更多