Программирование на Python с использованием FTP и списков

#python #ftp

#python #ftp

Вопрос:

Моя главная цель — в любое время проверять FTP-сервер на наличие новых файлов, а затем генерировать .txt-файл, содержащий только новые файлы, скопированные туда. Если новых файлов нет, он ничего не возвращает. Вот что у меня есть на данный момент. Я начал с копирования файлов с сервера в oldlist.txt , затем подключается к FTP-сайту и сравнивает данные с newlist.txt и oldlist.txt и различия, которые я хочу видеть во временном FTP-файле changes.txt . Каждый раз, когда я подключаюсь, я буду менять newlist.txt и сделать это oldlist.txt чтобы я мог сравнить при следующем подключении. Есть ли лучший способ сделать это? Кажется, что мои списки никогда не меняют данные каждый раз. Извините, если это сбивает с толку, спасибо.

 import os
filename = "oldlist.txt"
testing = "newlist.txt"
tempfilename = "Temporary FTP file Changes.txt"

old = open(filename, "r")
oldlist = old.readlines()
oldlist.sort()


from ftplib import FTP
ftp = FTP("ftpsite", "username", "password")
ftp.set_pasv(False)
newlist = []
ftp.dir(newlist.append)
newlist.sort()
ftp.close()

bob = open(testing, "w")
for nl in newlist:
    bob.write(nl   "n")


hello = open(tempfilename, "w")

for c in newlist:
    if c not in oldlist:
    hello.write(c   "n")

bob.close()
old.close()   
hello.close()

os.remove("oldlist.txt")

os.rename("newlist.txt", "oldlist.txt")
  

Ответ №1:

Немного проще / быстрее преобразовать списки в набор и не беспокоиться о сортировке.

 for filename in set(newlist) - set(oldlist):
    print 'New file: ', filename
  

Кроме того, вместо сохранения списка в файл в виде необработанного текста вы можете использовать модуль shelve для создания постоянного хранилища, к которому удобно обращаться, как к обычному Python dict.

В противном случае ваш код обладает преимуществами простоты и прямолинейности.

Вот проработанный пример:

 from ftplib import FTP
import shelve

olddir = shelve.open('filelist.shl')   # create a persistent dictionary

ftp = FTP('ftp1.freebsd.org')
ftp.login()

result = []
ftp.dir(result.append)
newdir = set(result[1:])

print ' New Files '.center(50, '=')
for line in sorted(set(newdir) - set(olddir)):
    print line
    olddir[line] = ''
print ' Done '.center(50, '=')
olddir.close()
  

Комментарии:

1. итак, вы говорите, что вместо создания oldlist.txt файл просто храните его где-нибудь, где я могу сравнить новый список с модулем, а затем вывести мои изменения в файл? Извините, если это неправильно, я очень новичок. И не могли бы вы также показать пример. Большое спасибо за вашу помощь! Также, когда я запускаю тот код, который вы мне дали, он просто показывает мне весь список с ftp-сервера. Мне просто нужны изменения, если они есть.

2. спасибо за ваш пример, Рэймонд. я попробую это в данный момент и посмотрю, что получится. Еще раз спасибо.

3. Raymond ваш код, похоже, отлично работает. но я собираюсь поменять местами код строки печати и просто скопировать его в текстовый файл, чтобы я мог запустить другой процесс. Спасибо за вашу помощь.

Ответ №2:

Ваша реализация этой схемы является разумной. Я бы не выбрал эту схему для реализации автоматического обмена сообщениями по FTP, если это то, что вы делаете. У этого подхода есть две слабые стороны:

  • Он не поддерживает повторяющиеся имена файлов. Любое имя файла, которое встречается в «старой» истории, не будет обнаружено как новый файл. Может быть, это проблема для вас, может быть, нет. Но даже если теперь имена файлов гарантированно уникальны, это не всегда может быть правдой.
  • Он не сообщает вам, готов ли новый файл к использованию или нет. Возможно, что новый файл будет обработан во время его загрузки. Некоторые люди применяют правило «без изменения размера в течение X секунд», но это только увеличивает задержку и по-прежнему оставляет уязвимость для разорванных соединений.

Одна из схем, которая похожа, но не имеет ни одной из этих двух проблем, заключается в том, чтобы фактически хранить файл на сервере с зарезервированным именем или в отдельном месте и использовать его временную метку (предпочтительно время модификации самого файла), чтобы решить, какие файлы могут быть безопасно обработаны. Этот файл «семафора» обновляется до текущего времени в качестве последнего шага при загрузке файла. Могут быть обработаны все файлы со временем модификации, более старым, чем временная метка семафора. После обработки все файлы должны быть удалены из папки загрузки, чтобы они не обрабатывались дважды. Я видел, как эта схема хорошо работает в автоматизированном потоке производственных данных.

Комментарии:

1. wberry, спасибо за ваш ответ. у меня нет проблем с файлами, имеющими одно и то же имя, каждый раз, когда клиент отправляет нам файл, в имени файла указывается дата и отметка времени. Я не совсем уверен, что вы имеете в виду во втором абзаце. у меня вроде как есть идея, но я не уверен, как реализовать это в моем коде. Большое спасибо!

2. Мой предпочтительный метод предотвращения частичного использования файлов на самом деле заключается в загрузке файлов во временную папку, а затем перемещении их в конечную папку после их загрузки. Затем потребитель может обработать любые файлы, которые он видит, а затем удалить их. Но разрешения FTP-сервера должны разрешать перемещение файлов, чтобы это работало.