如果您在linux和Windows之间共享文件,则python zipfile库出现问题

问题描述

zipfile module对于使用python管理.zip文件非常有趣。

但是,如果.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,'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])]

您如何看待? 有没有更直接或更Python的方式来完成这项工作?

解决方法

我刚刚理解了@snakecharmerb的答案以及阅读他提出的链接。谢谢@snakecharmerb向我展示方法... 实际上,确实如建议的链接中所述,内部zipfile仅使用'/',并且独立于所使用的OS。我喜欢具体地看事物,所以我做了这个小测试:

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

    • testZipWindows
      • foo1.txt
      • InFolder
        • foo2.txt
  • 我在Linux OS上为testZipFedora.zip存档做了同样的事情(并且也没有使用命令行):

    • testZipFedora
      • foo1.txt
      • InFolder
        • 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])]

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