0

使用 python 管理 .zip 文件的zipfile 模块非常有趣。

但是,如果 .zip 文件是在 linux 系统或 macos 上创建的,则分隔符当然是“/”,如果我们尝试在 Windows 系统上使用此文件,则可能会出现问题,因为分隔符是“\”。因此,例如,如果我们尝试确定 .zip 文件中压缩的目录根目录,我们可以考虑如下:

from zipfile import ZipFile, is_zipfile
import os

if is_zipfile(filename):

    with ZipFile(filename, 'r') as zip_ref:
        packages_name = [member.split(os.sep)[0] for member in zip_ref.namelist()
                         if (len(member.split(os.sep)) == 2 and not
                                                       member.split(os.sep)[-1])]

但是在这种情况下,我们总是得到 packet_name = [] 因为 os.sep 是“\”,而由于压缩是在 linux 系统上完成的,所以路径是 'foo1/foo2'。

为了管理所有情况(在 linux 系统上压缩并在 Windows 系统上使用或相反),我想使用:

from zipfile import ZipFile, is_zipfile
import os

if is_zipfile(filename):

    with ZipFile(filename, 'r') as zip_ref:

        if all([True if '/' in el else
                False for el in zip_ref.namelist()]):
            packages_name = [member.split('/')[0] for member in zip_ref.namelist()
                             if (len(member.split('/')) == 2 and not
                                                       member.split('/')[-1])]

        else:
            packages_name = [member.split('\\')[0] for member in zip_ref.namelist()
                             if (len(member.split('\\')) == 2 and not
                                                           member.split('\\')[-1])]

你觉得这怎么样?有没有更直接或更pythonic的方式来完成这项工作?

4

1 回答 1

1

感谢@snakecharmerb 的回答和对他提出的链接的阅读,我才明白。谢谢@snakecharmerb 向我展示了方式......事实上,正如所建议的链接中所描述的那样,内部 zipfile 仅使用 '/' 并且这与所使用的操作系统无关。因为我喜欢具体地看待事物,所以我做了这个小测试:

  • 在 Windows 操作系统上,我使用该操作系统的常用方法(不在命令行中)创建了一个包含此树结构的文件 testZipWindows.zip:

    • 测试ZipWindows
      • foo1.txt
      • 文件夹
        • foo2.txt
  • 我在 linux 操作系统上(也没有使用命令行)为 testZipFedora.zip 存档做了同样的事情:

    • 测试ZipFedora
      • foo1.txt
      • 文件夹
        • foo2.txt

这是结果:

$ python3
Python 3.7.9 (default, Aug 19 2020, 17:05:11) 
[GCC 9.3.1 20200408 (Red Hat 9.3.1-2)] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> from zipfile import ZipFile
>>> with ZipFile('/home/servoz/Desktop/test/testZipWindows.zip', 'r') as WinZip:
...  WinZip.namelist()
... 
['testZipWindows/', 'testZipWindows/foo1.txt', 'testZipWindows/InFolder/', 'testZipWindows/InFolder/foo2.txt']
>>> with ZipFile('/home/servoz/Desktop/test/testZipFedora.zip', 'r') as fedZip:
...  fedZip.namelist()
... 
['testZipFedora/', 'testZipFedora/foo1.txt', 'testZipFedora/InFolder/', 'testZipFedora/InFolder/foo2.txt']

所以一切都亮了!我们确实必须使用 os.path.sep 才能在多平台中正常工作,但是当我们处理 zipfile 库时,绝对有必要使用 '/' 作为分隔符,而不是 os.sep(或 os.path.sep)。那是我的错!!!

因此,对于我的第一篇文章的示例,以多平台方式使用的代码就是:

from zipfile import ZipFile, is_zipfile
import os

if is_zipfile(filename):

    with ZipFile(filename, 'r') as zip_ref:
        packages_name = [member.split('/')[0] for member in zip_ref.namelist()
                             if (len(member.split('/')) == 2 and not
                                                       member.split('/')[-1])]

而不是我想象的所有无用的东西......

于 2020-10-18T08:44:46.950 回答