为什么python不能执行通过stdin传递的zip存档?

Jer*_*NER 3 python compression zip python-2.6

我有一个包含__main__.py文件的zip存档:archive.zip

我可以执行它

python archive.zip
=> OK !
Run Code Online (Sandbox Code Playgroud)

但没有

cat archive.zip | python
=> File "<stdin>", line 1
SyntaxError: Non-ASCII character '\x9e' in file <stdin> on line 2,
but no encoding declared; see http://www.python.org/peps/pep-0263.html for details
Run Code Online (Sandbox Code Playgroud)

为什么两种模式之间存在差异?有没有办法让管道在没有解压缩到python之外的情况下工作?

我通过网络收到这个存档,并希望我收到它后尽快执行它,所以我认为将zip管道输入python会起作用!

syn*_*tel 6

你可以'python file.zip'而不是'cat file.zip |的原因 python'是Python内置了'zipimport',因此当你对文件运行python(或尝试导入它们)时,zipimport会在导入过程中对它们进行破解.(有关详细信息,请参阅导入模块).

但是使用stdin,python不会尝试搜索流数据 - 因为流数据可能是任何东西 - 可能是由代码处理的用户输入,可能是代码.没有办法知道,并且Python没有真正努力知道这个原因.

编辑

偶尔,当你回答问题时 - 你会想'我真的不应该告诉别人答案',不是因为你希望保密或对他们持有一些权力.仅仅因为他们走下去的路径不是正确的道路,你想帮助他们走出他们正在挖掘的洞.这是其中一种情况.然而,根据我更好的判断,这是一种非常黑客的方式来完成类似于你想要的东西.这不是最好的方式,实际上可能是最糟糕的方式.

我只是玩了一段时间的zipimporter并尝试了我能想到的所有技巧.我也看了'imp','compile'.到目前为止,我没有什么可以从内存中导入一个压缩模块(或鸡蛋).因此,需要一个临时步骤.

我会在前面说这个,我很尴尬甚至发布这个.不要向与你合作的人或你尊重的人展示这一点,因为他们嘲笑这个可怕的解决方案.

这是我做的:

mkdir foo
echo "print 'this is foo!'" >>foo/__init__.py
zip foo.zip -r foo
rm -rf foo                   # to ensure it doesn't get loaded from the filesystem
mv foo.zip somethingelse.zip # To ensure it doesn't get zipimported from the filesystem
Run Code Online (Sandbox Code Playgroud)

然后,我使用了这个程序

cat somethingelse.zip | python script.py

#!/usr/bin/python 

import sys
import os
import zipfile
import StringIO
import zipimport
import time

sys.path.append('/tmp')

class SinEater(object):
    def __init__(self):
        tmp = str(int(time.time()*100)) + '.zip'
        f = open(tmp, 'w')
        f.write(sys.stdin.read(1024*64)) # 64kb limit
        f.close()
        try:
            z = zipimport.zipimporter(tmp)
            z.load_module('foo')

        except:
            pass

if __name__ == '__main__':
    print 'herp derp'
    s = SinEater()
Run Code Online (Sandbox Code Playgroud)

生产:

herp derp
this is new
Run Code Online (Sandbox Code Playgroud)

一个比这个好大约一百万倍的解决方案是拥有一个文件系统通知(inotify,kevent,无论使用什么窗口),它可以监视新zip文件的目录.当在该目录中删除新的zip文件时,您可以自动zipimport它.但是,即使解决方案很糟糕,我也不能强调.我对Ansible(实际上没什么)了解得太多,但我无法想象任何工程师都认为这对于如何处理代码更新或远程控制来说是一个很好的解决方案.