在第二个循环中使用 ftplib returns "No such file or directory" 循环遍历 ftp 中的文件

Looping through files in ftp using ftplib returns "No such file or directory" in second loop

我正在尝试遍历 ftp 上的文件,然后存储它们。但是,在第二次迭代中,我收到错误:

FileNotFoundError: [Errno 2] No such file or directory:

这是我的代码:

# TODO: auth
from ftplib import FTP

def extract(environment):

    ftp = FTP(auth["host"])

    # Monitor and extract
    with ftp.login(user=auth['username'], passwd=auth['password']) as ftp:

        folders = []
        try:
            folders = ftp.nlst()
        except:
            print('Probably no folders in this directory')

        for f in folders:

            # Go into subfolder per subfund
            path = "".join(['/',f])
            ftp.cwd(path)

            # List files
            files = []
            try:
                files = ftp.nlst()
            except:
                print('Probably no files in this directory')

            for filename in files:
                if ".csv" in filename:

                    with open(filename, 'r+') as source_file:

                        print('opened, this works for the 1st only')
                        store_to_gcs(source_file, filename)


def store_to_gcs(source_file, filename)
    # TODO: bucket = storage.bucket(app=app)
    # After it I store it to GCS, does it have anything to do with it?

    storage_ref = "test/" + filename
    blob = bucket.blob(storage_ref)
    blob.upload_from_file(source_file)

with open(filename, 'r+') as source_file 仅对文件中的第一个文件有效,对第二个文件无效。

我可以确认我在正确的目录中,正如我所做的那样 ftp.pwd() 确认。

open(filename, 'r+') 打开本地文件。虽然我相信你想打开一个远程文件。

您可能有 ffpos1_708524_57474156_18022019_036521_1.csv 的本地副本,但没有 fflia1_708470_57474842_18022019_036521_1.csv 的本地副本。这可以解释为什么 open 似乎第一次迭代成功。


ftplib 中没有类似 open 的函数。


有两种解决方法:

  • 将文件下载到内存中 - 即 BytesIO 类文件对象。
    参见

    然后您可以将 BytesIO 传递给 blob.upload_from_file

    这很容易实现,但如果文件太大,可能会出现问题。

    for filename in files:
        if ".csv" in filename:
            flo = BytesIO()
            ftp.retrbinary('RETR ' + filename, flo.write)
    
            flo.seek(0)
            store_to_gcs(flo, filename)
    
  • 实现一个自定义类文件对象,可以根据需要即时读取远程文件。这更复杂,但有可能。
    .