线程或多处理

时间:2013-08-14 02:21:45

标签: python multithreading

我有一些我想加速的代码。我的目标是下载并保存大约一百万个文件。我正在使用请求库来访问内容。我比以前更困惑。大多数Q / A建议正确的方法是在任务受I / O限制时使用线程模块,因为我连接到服务器,等待响应,然后将响应写入磁盘,我的任务是I / O界限。

但后来我读了这样的东西

单个进程中可以存在多个线程。属于同一进程的线程共享相同的内存区域(可以读取和写入相同的变量,并且可以相互干扰)。

我的代码是这样的 - 在线程之前

def create_list(some_ftp_site):
    # do some stuff to compare the list to
    #  the last list  and return the difference in the two

    return list_to_pull


def download_and save_the_file(some_url):
   thestring = requests.get(some_url).content
   file_ref = open(something)
   fileref.write(the_string)
   fileref.close()


if __name__ == '__main__'
   files_to_get = create_list(some_ftp_site)
   if len(files_to_get) != 0:
       for file_to_get in files_to_get:
           download_and_save(file_to_get)

使用任何一个都是为了我的深入跳跃。因此,如果我多线程这个,我担心我会发生意想不到的事情,例如某个文件的前半部分连接到另一个文件的后半部分。

这种类型的任务是否更适合多处理或多线程。很明显,我不会知道两个不同的文件部分是否连接在一起,因为它们写入了相同的变量

4 个答案:

答案 0 :(得分:4)

要么可以工作,但多处理将更安全,也许更容易实现。请记住,特别是对于Python,Global Interpreter Lock意味着多个线程不会从多个内核中获得太多好处,而多处理则不是问题。

答案 1 :(得分:2)

由于您正在构建IO绑定应用程序,因此大部分应用程序将在您下载数据时保持阻止状态。无论您使用线程还是多处理,都是如此。如果你真的想下载一些严肃的数据,可以使用像gevent for python这样的并发框架。还有其他一些,但是这个框架将允许您以非阻塞状态进行IO调用。换句话说,它就是为这种负载而设计的。

如果您进入穿线路线,您最终会遇到可以创建多少线程的墙。

对于可以并行运行的进程数也是如此。

例如,使用gevent可以创建成千上万的“绿色”线程,因为它们的创建成本非常低。

http://www.gevent.org

答案 2 :(得分:2)

线程可能变得混乱,需要通过互斥锁进行各种锁定。您的应用程序似乎适合多处理,易于实现。把你的代码放在一个方法中说:

def download_and_save_the_file(some_url):
    thestring = requests.get(some_url).content
    #Make sure you create unique names
    something = unique_filename(some_url)
    file_ref = open(something)
    fileref.write(the_string)
    fileref.close()  

然后使用多处理和URL列表创建一个池,并行下载将继续:

from multiprocessing import Pool,cpu_count

p = Pool(cpu_count()-1)
p.map(download_and_save_the_file,files_to_get)

答案 3 :(得分:1)

如果您想加速您的应用程序,那么您将不得不进行多处理,而不是多线程。 Python中的GIL意味着线程不是完全独立的执行路径,就像在其他语言中使用的那样。如果您要运行许多进程,您可能希望考虑将Python托管在哪个操作系统上; Windows中的进程间上下文切换时间不是特别快。

与任何多进程/多线程应用程序一样,有必要确保每个进程或线程正在进行大量工作,否则您的应用程序将全部上下文切换并减少实际运行...