【问题标题】:Find out differences between directory listings on time A and time B on FTP找出 FTP 上时间 A 和时间 B 的目录列表之间的差异
【发布时间】:2019-01-03 05:22:46
【问题描述】:

我想构建一个脚本来找出 FTP 服务器上的哪些文件是新文件,哪些文件已经处理。
对于 FTP 上的每个文件,我们读取信息、解析它并将我们需要的信息从它写入我们的数据库。这些文件是 xml 文件,但必须翻译。

目前我正在使用 mlsd() 获取列表,但这需要 4 分钟,因为此目录中已经有 15.000 个文件 - 每天都会更多。

我不想将此列表与我保存在文本文件中的旧列表进行比较,我想知道是否有更好的可能性。
因为此任务必须“实时”运行,所以它会每隔 1 或 2 分钟以 cronjob 结束。如果这个方法需要很长时间,这将不起作用。

解决方案应该是 PHP 或 Python。

def handle(self, *args, **options):
    ftp = FTP_TLS(host=host)
    ftp.login(user,passwd)
    ftp.prot_p()
    list = ftp.mlsd("...")
    for item in list:
       print(item[0] + " => " + item[1]['modify'])

此代码示例已经运行了 4 分钟。

【问题讨论】:

  • 我建议不要将一个列表与另一个列表进行比较,而是保存最后一个查询的时间戳并查找自该时间戳以来创建的文件。
  • @J.Ghyllebert 为此你仍然必须使用mlsd,所以我认为它不能解决 OP 的问题。
  • 这就是我之前的想法。最新的想法是运行 mlsd -> 创建一个列表 -> 将已解析的文件压缩到 backup.zip 中并删除单个文件。下次运行 mlsd 它将排除 zip 并且运行时应该更好?
  • @Rune 不是每次都创建一个 zip,您还可以将处理后的文件移动到另一个目录。
  • 搬家是个好主意。压缩不是,因为您不能在 FTP 服务器上压缩文件。您必须下载它们,删除远程副本,在本地压缩并上传 zip(这对我来说毫无意义)。 -- 虽然这些都不是真正的答案 “找出时间 A 上的目录列表和 ftp 上的时间 B 之间的区别” -- 如果您正在寻找这样的解决方案,您应该真正改变您的问题标题。

标签: python ftp ftplib


【解决方案1】:

我一直尽量避免浏览文件夹以查找可能发生的更改。我更喜欢设置专门的工作流程。当只能添加文件(或现有文件的新版本)时,我尝试使用一种工作流程,将文件添加到一个目录中,然后进入存档它们的其他目录。处理可以发生在文件在使用后被删除的目录中,或者当它们从一个文件夹复制/移动到另一个文件夹时。

作为一个小小的好处,我还使用了复制/重命名模式:首先使用临时名称(例如 .t 前缀或后缀)复制文件,并在复制结束时重命名。这可以防止尝试处理未完全复制的文件。好的,当我们有慢行时它曾经更重要,但应该尽可能避免竞争条件,它允许使用每 10 秒或更短时间轮询文件夹的守护进程。

不确定它在这里是否真的相关,因为它可能需要一些重构,但它提供了防弹解决方案。

【讨论】:

    【解决方案2】:

    如果 FTP 是您与服务器的唯一接口,那么没有比您已经在做的更好的方法了。

    除非你的服务器支持非标准的-t 切换到LIST/NLST 命令,这会返回按时间戳排序的列表。
    How to get files in FTP folder sorted by modification time

    如果需要很长时间的是文件列表的下载(不是下载的开始)。在这种情况下,您可以请求排序列表,但只下载前导的新文件,一旦找到第一个已处理的文件就会中止列表。

    有关如何中止文件列表下载的示例,请参阅:
    Download the first N rows of text file in ftp with ftplib.retrlines

    类似这样的:

    class AbortedListing(Exception):
        pass
    
    def collectNewFiles(s):
        if isProcessedFile(s): # your code to detect if the file was processed already
            print("We know this file already: " + s + " - aborting")
            raise AbortedListing()
        print("New file: " + s)
    
    try:
        ftp.retrlines("NLST -t /path", collectNewFiles)
    except AbortedListing:
        # read/skip response
        ftp.getmultiline()
    

    【讨论】:

    • 如果我的ftp支持这个方法我会试试。好的和干净的想法。也许我会通过将带有最后检索项目的时间戳的文本文件保存到 ftp 来改进它?所以我只需要将排序列表的修改时间与文本文件中的修改时间进行比较,如果它较旧则中止。
    • 嗨,我选择了最简单的方法,即使我发现你的方法更好。我现在只是将已解析的文件复制到子目录中。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-03-06
    • 1970-01-01
    • 1970-01-01
    • 2011-05-17
    • 2013-07-12
    • 1970-01-01
    相关资源
    最近更新 更多