2015-05-03 3 views
1

Я пытаюсь использовать несколько файлов, используя ftp. Однако, вместо того, чтобы загружать несколько разных файлов, он загружает один файл несколько раз. Что с этим не так?Загрузка нескольких файлов с использованием ftplib и многопроцессорной обработки

import fnmatch 
import os 
from multiprocessing import Pool 
import ftplib 

file_extensions = [ '*.mp4', '*wmv' ] 
matches = [] 
#match = [] 
exclude = "/ext_hdd/download/incomplete" 
def upload(file): 
    ftp = ftplib.FTP('ftp.domain.com') 
    ftp.login("username","password") 
    f = open(match,'rb') 
    print ("uploading" + match) 
    ftp.storbinary('STOR %s' %match, f) 
    f.close() 
    ftp.quit() 

for root, dirs, filenames in os.walk("/ext_hdd/download"): 
     dirs[:] = [d for d in dirs if d not in exclude] 
     for extension in file_extensions: 
      for filename in fnmatch.filter(filenames, extension): 
        matches.append(os.path.join(root, filename)) 
        (match for match in matches if file_size > 209715200) 
        #print matches 
        for match in matches: 
         pool = Pool(2) 
        pool.map(upload,match) 

ответ

1

Существует несколько вопросов. Во-первых, вы повторяете все файлы в заданном каталоге, которые соответствуют определенному расширению файла, и добавьте его в список с именем matches. Но затем, внутри этого цикла, вы также повторяете matches и вызываете Pool.map по каждому элементу. Это означает, что если у вас есть два соответствующих файлов, ваш код в основном эквивалентно следующему:

for filename in ["file1.mp4", "file2.mp4"]: 
    matches.append(os.path.join(root, filename)) 
    for match in matches: 
     pool_stuff(filename) 

Это будет в конечном итоге вызова pool_stuff на filename дважды, потому что он перебирает matches дважды. То же самое происходит и с вашим кодом.

Вторая проблема заключается в том, что вы создаете новый Pool на каждой итерации своего внутреннего цикла, что совсем не то, что вы хотите делать. Вы просто хотите создать Pool один раз и передать все свои совпадения. Вам также не нужно использовать map, так как вы передаете одну задачу за раз до Pool. Вместо этого вы можете использовать apply_async для передачи задач при повторном и фильтровании файлов. Вот пример очистки.

import fnmatch 
import os 
from multiprocessing import Pool 
import ftplib 

file_extensions = [ '*.mp4', '*wmv' ] 
exclude = "/ext_hdd/download/incomplete" 
def upload(match): 
    ftp = ftplib.FTP('ftp.domain.com') 
    ftp.login("username","password") 
    f = open(match,'rb') 
    print ("uploading" + match) 
    ftp.storbinary('STOR %s' %match, f) 
    f.close() 
    ftp.quit() 

if __name__ == "__main__": 
    pool = Pool(2) 
    tasks = [] 
    for root, dirs, filenames in os.walk("/ext_hdd/download"): 
     for extension in file_extensions: 
      for filename in fnmatch.filter(filenames, extension): 
       match = os.path.join(root, filename) 
       tasks.append(pool.apply_async(upload, args=(match,))) 

    # Get the result of each task, just so any 
    # exceptions thrown in the workers will be raised. 
    for task in tasks: 
     task.get() 
    pool.close() 
    pool.join() 

Обратите внимание, что я удалил некоторый код из вашего исходного примера, который, по-видимому, не использовался ни для чего.

+0

Что такое x.get()? Кроме того, где я должен вставить раздел ftplib? –

+0

Будет здорово, если бы вы могли переработать мой примерный код, это могло бы помочь мне понять всю картину, в том числе, где вставить раздел сравнения размера файла и раздел загрузки ftp. Благодарю. –

+0

@ ThomasG.Lau Я обновил пример, чтобы показать функцию «upload». Надеюсь, это уточнит ваш второй вопрос. 'x.get()' должен был сказать 'task.get()' (извините за это) и является вызовом ['AyncResult.get'] (https://docs.python.org/2/library/multiprocessing .html # multiprocessing.pool.AsyncResult.get). Он используется для ожидания завершения функции, которую вы передали в pool.apply_async, и возврата ее результата. Я просто использую его, чтобы вы увидели, произошла ли ошибка в 'upload'. Если вы оставите вызов 'task.get()', они будут выполняться молча, что может сбить с толку. – dano

Смежные вопросы