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.py
和 zipedFile.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中找不到