zipfile 写入在 gcloud 中找不到文件

Posted

技术标签:

【中文标题】zipfile 写入在 gcloud 中找不到文件【英文标题】:zipfile write dont find files in gcloud 【发布时间】:2020-01-17 20:48:16 【问题描述】:

我正在尝试从 Google 存储中压缩一些文件。

Python的zipfile在gcloud中没有找到文件,只在项目中。

如何为我的代码找到 gcloud 中的文件?

    zip_buffer = io.BytesIO()
    with zipfile.ZipFile(zip_buffer, 'w') as zip_file:
        for revenue in revenues:
        # queryset with files a lot, so, for a each file, add in zip
            t = tempfile.NamedTemporaryFile()
            t.write(revenue.revenue.name)
            if revenue.revenue.name:
                t.seek(0)
                with default_storage.open(revenue.revenue.name, "r") as file_data:
                    zip_file.write(file_data.name, compress_type=zipfile.ZIP_DEFLATED)
                    # the code dont pass from this part
                t.close()
    response = HttpResponse(content_type='application/x-zip-compressed')
    response['Content-Disposition'] = 'attachment; filename=my_zip.zip'
    response.write(zip_buffer.getvalue())
    return response

在这一部分中,我编写了从 gcloud 打开的文件,但在函数内部停止:

def write(self, filename, arcname=None, compress_type=None):
    """Put the bytes from filename into the archive under the name
    arcname."""
    if not self.fp:
        raise RuntimeError(
              "Attempt to write to ZIP archive that was already closed")
    st = os.stat(filename) 
    # when I try find the file, the command os.stat search in project, not in gcloud 

“os.stat(filename)”在项目中搜索文件,如何在gcloud中查找?

【问题讨论】:

你是什么意思,for my code find the files in gcloud?这里没有太多代码可以使用。 项目树中文件的代码搜索,但我需要在 gcloud 中搜索 您能说得更清楚些吗?您是否在 Cloud Storage 存储分区中保存了一些文件并且想要访问它们?您是否有保存在 Cloud Shell 中的文件并且想要访问它们?还是您在个人计算机上使用 Cloud SDK 并且想要获取一些文件? 第一个选项。我将文件保存在 gcloud 存储桶中,然后我可以阅读,然后我不能是 zip。我正常读取文件,但是当我压缩它时,Python 的“zipfile”本机在您的本机进程中找不到 gcloud 中的文件,因为它正在搜索项目,而不是 gcloud。 【参考方案1】:

我将发布我的发现作为答案,因为我想评论一些事情。

我明白了:

    您有一个 Python 库 zipfile 用于处理 ZIP 文件。 您在本地查找文件,并一一添加到 ZIP 文件中。 您也希望对位于 Google Cloud Storage 存储分区中的文件执行此操作。但它无法找到文件。

如果我误解了用例场景,请在评论中进一步详细说明。

但是,如果这正是您想要执行的操作,则不支持此操作。在*** Question - Compress files saved in Google cloud storage 中指出,无法压缩 Google 云存储 中已有的文件。该问题的解决方案是订阅新创建的文件,然后在本地下载它们,压缩它们并在 GCS 中覆盖它们。如您所见,您可以列出文件,或遍历存储在 GCS 中的文件,但您首先需要下载它们才能处理它们。

解决方法

因此,在您的用例场景中,我建议使用 Python 客户端 API 采用以下解决方法:

    您可以使用Listing objects Python API,从GCS 中获取所有对象。 然后您可以使用Downloading objects Python API,将对象下载到本地。 只要对象位于本地目录,您就可以使用zipfile Python 库将它们压缩在一起,就像您已经在做的那样。 然后对象被压缩,如果您不再需要下载的对象,您可以使用os.remove("downloaded_file.txt") 删除它们。 如果您需要在 Google Cloud Storage 存储桶中保存压缩的 ZIP 文件,则可以使用Uploading objects Python API 将 ZIP 文件上传到 GCS 存储桶中。

如上所述,不支持直接在 Google Cloud Storage 存储桶中处理文件(例如,将它们添加到 ZIP 文件等)。您首先需要在本地下载它们才能这样做。希望我的解决方法对您有所帮助。

更新

正如我上面提到的,不支持在 GCS 存储桶中压缩文件。因此,我在 Python 中为您准备了一个working example,以了解如何使用该解决方法。

注意:由于我不擅长使用 Python 操作 os 命令 图书馆,我不熟悉zipfile图书馆,有 可能是实现这一目标的更好和更有效的方法。然而, 可以在this GitHub link 中找到的代码执行以下操作 程序:

#Public variables: 部分下,将BUCKET_NAME 更改为您相应的存储桶名称并在Google Cloud Shell 中执行python 脚本。 Cloud Shell 现在我的bucket结构如下:
gs://my-bucket/test.txt
gs://my-bucket/test1.txt
gs://my-bucket/test2.txt
gs://my-bucket/directory/test4.txt

执行命令时,应用程序的作用如下:

    将获取脚本执行的路径。例如/home/username/myapp。 它将在此目录中创建一个临时目录,例如/home/username/myapp/temp 它将遍历您指定的存储桶中的所有文件,并将它们下载到本地临时目录中。

    注意:如果存储桶中的文件在目录下,它将简单地下载文件,而不是再次创建该子目录。您可以修改代码以使其在以后按您的需要工作。

    所以新下载的文件将如下所示:
/home/username/myapp/temp/test.txt
/home/username/myapp/temp/test1.txt
/home/username/myapp/temp/test2.txt
/home/username/myapp/temp/test4.txt
    之后,代码会将所有这些文件压缩到一个新的zipedFile.zip,该zipedFile.zip 将与您执行的main.py 脚本位于同一目录中。 此步骤也完成后,脚本将删除目录/home/username/myapp/temp/ 及其所有内容。

如上所述,在本地执行脚本后,您应该能够看到 main.pyzipedFile.zip 文件,其中包含 GCS 存储桶中的所有压缩文件。现在你可以根据你的项目需要来考虑实现的想法并修改它。

【讨论】:

谢谢哥们!!你的帮助非常有用!!所以,即使我可以毫不费力地从 GCS 下载它,我也无法压缩它?为此,我需要在我的项目中下载它,然后全部压缩,对吗?那是唯一的选择吗?我不能那样做,如果可以的话,我的项目将在你的结构中有很多文件。我通常下载文件时的想法是相同的。我在 GCS 中打开了一个文件并将其写入返回的 HttpResponse 中。我正常阅读,我的变量是一个文件,但是当我用它来写入 ZipFile 时,库再次搜索我项目中的文件(现在来了你的帮助)。 如果我遗漏了什么或误解了,请改写。 1. 您可以在本地压缩它,而不是在文件在 GCS 中时。 2.是的,您需要先下载它。 3. 目前这是唯一的选择。 4.您可以将所有要压缩的文件下载到自定义的本地目录中。压缩它们,然后在压缩完成后立即删除它们。所以你总是会得到压缩文件而不是所有下载的文件。 我尝试这样做,但无法在我的项目中下载它,我尝试将其保存在项目树的目录中。我该怎么办? 再次感谢大家的帮助!! 您好,请在答案中查看我的更新部分。我提供了一个工作代码,如果您在 Cloud Shell 中执行它,它将完全按照指定的解决方法执行。您可以根据项目的需要进行基本的实现和修改代码。【参考方案2】:

最终代码:

zip_buffer = io.BytesIO()
base_path = '/home/everton/compressedfiles/'
fiscal_compentecy_month = datetime.date(int(year), int(month), 1)
revenues = CompanyRevenue.objects.filter(company__pk=company_id, fiscal_compentecy_month=fiscal_compentecy_month)

if revenues.count() > 0:
    path = base_path + str(revenues.first().company.user.pk) + "/"
    zip_name = "---".format(revenues.first().company.external_id, revenues.first().company.external_name, month, year)

    for revenue in revenues:
        filename = revenue.revenue.name.split('revenues/')[1]
        if not os.path.exists(path):
            os.makedirs(path)
        with open(path + filename, 'wb+') as file:
            file.write(revenue.revenue.read())
        file.close()

    with zipfile.ZipFile(zip_buffer, 'w') as zip_file:
        for file in os.listdir(path):
            zip_file.write(path + file, compress_type=zipfile.ZIP_DEFLATED)
    zip_file.close()

    response = HttpResponse(content_type='application/x-zip-compressed')
    response['Content-Disposition'] = 'attachment; filename=.zip'.format(zip_name)
    response.write(zip_buffer.getvalue())
    shutil.rmtree(path)
    return response

【讨论】:

以上是关于zipfile 写入在 gcloud 中找不到文件的主要内容,如果未能解决你的问题,请参考以下文章

在当前项目和插件组 [org.apache.maven.plugins, org.codehaus.mojo] 中找不到前缀“gcloud”的插件

gcloud错误:ApiError:在新的util.ApiError中找不到

云中的 Zipfile 文件(amazon s3),无需先将其写入本地文件(无写入权限)

服务扩展写入核心数据,但在应用程序中找不到任何内容

zipfile 模块

Python - 将文件夹及其内容写入 ZipFile