我有一些我想加速的代码。我的目标是下载并保存大约一百万个文件。我正在使用请求库来访问内容。我比以前更困惑。大多数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)
使用任何一个都是为了我的深入跳跃。因此,如果我多线程这个,我担心我会发生意想不到的事情,例如某个文件的前半部分连接到另一个文件的后半部分。
这种类型的任务是否更适合多处理或多线程。很明显,我不会知道两个不同的文件部分是否连接在一起,因为它们写入了相同的变量
答案 0 :(得分:4)
要么可以工作,但多处理将更安全,也许更容易实现。请记住,特别是对于Python,Global Interpreter Lock意味着多个线程不会从多个内核中获得太多好处,而多处理则不是问题。
答案 1 :(得分:2)
由于您正在构建IO绑定应用程序,因此大部分应用程序将在您下载数据时保持阻止状态。无论您使用线程还是多处理,都是如此。如果你真的想下载一些严肃的数据,可以使用像gevent for python这样的并发框架。还有其他一些,但是这个框架将允许您以非阻塞状态进行IO调用。换句话说,它就是为这种负载而设计的。
如果您进入穿线路线,您最终会遇到可以创建多少线程的墙。
对于可以并行运行的进程数也是如此。
例如,使用gevent可以创建成千上万的“绿色”线程,因为它们的创建成本非常低。
答案 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中的进程间上下文切换时间不是特别快。
与任何多进程/多线程应用程序一样,有必要确保每个进程或线程正在进行大量工作,否则您的应用程序将全部上下文切换并减少实际运行...