不确定为什么会发生这种情况,但是当我在命令行中运行解压缩文件(例如apache-groovy-binary-2.4.7.zip)时……
>目录是rwx-r-xr-x
>文件是rwxr-xr-x或rw-r – r–
但是当我从同一文件上的Python 2.7脚本运行zipfile.extractall()时……
>目录是rwx-r-x —
>文件都是rw-r —- – 甚至是那些应该是可执行文件的文件.
我的umask设置是0027-这部分解释了发生了什么,但为什么可执行位从所有文件中删除?
让Python在命令行版本中采用类似行为的最简单的解决方法是什么(当然,除了炮轰外!)?
解决方法
原因可以在zipfile.py中的_extract_member()方法中找到,它只调用shutil.copyfileobj(),它将在没有任何执行位的情况下写入输出文件.
解决这个问题的最简单方法是通过继承ZipFile并更改extract()(或在扩展版本中修补.默认情况下它是:
def extract(self,member,path=None,pwd=None): """Extract a member from the archive to the current working directory,using its full name. Its file information is extracted as accurately as possible. `member' may be a filename or a ZipInfo object. You can specify a different directory using `path'. """ if not isinstance(member,ZipInfo): member = self.getinfo(member) if path is None: path = os.getcwd() return self._extract_member(member,path,pwd)
应该更改最后一行以实际根据原始属性设置模式.你可以这样做:
import os from zipfile import ZipFile,ZipInfo class MyZipFile(ZipFile): def extract(self,pwd=None): if not isinstance(member,ZipInfo): member = self.getinfo(member) if path is None: path = os.getcwd() ret_val = self._extract_member(member,pwd) attr = member.external_attr >> 16 os.chmod(ret_val,attr) return ret_val with MyZipFile('test.zip') as zfp: zfp.extractall()
(以上是基于Python 3.5并假设zipfile名为test.zip)