反向工程Python为字符串
问题:有没有办法把Python对象反向工程成字符串?
信息:我现在正在做一个项目,目的是把我教授的研究分发到几十台电脑上,而不仅仅是他自己的电脑。作为一个好程序员,我想把这个程序做得更通用,可以用于不止他特定的程序。因此,运行他代码的电脑上没有,也不会有他的.py文件可以导入。我过去解决这个问题的方法是,他只需要把所有代码放在一个文件里,然后把这个文件的路径传给我的系统,我的系统就能把这个文件里的代码当作字符串导入(使用了从这个问题中得到的信息)。
但这让我开始思考。我现在可以从字符串中导入代码,并且代码能正常执行,这很好,但我在想,有没有办法让我不需要让他把代码文件传给我?特别是我在想这样的情况:假设他在他的文件里有这些内容:
def hello():
print "Hello world!"
导入这个文件后,“hello”会被添加到全局命名空间。但现在我想把它通过网络传输。你不能对“hello”使用pickle,它根本不行,我试过,pickle直接拒绝。
在另一端,我有节点电脑使用“exec code in newMod.dict”来生成代码。所以如果我能把“hello”通过某个函数处理,返回给我“def hello():\n print \"Hello world!\"”,这样我的exec方法就能运行,那我就成功了。这样我就可以让他有不止一个文件,因为我可以反向工程他所有非标准的导入。
老实说,我期待的答案可能是否定的,但我觉得试试看也是值得的。简单来说,我想把一个已经导入的模块转换成字符串。
2 个回答
0
使用 marshal模块,你可以把代码对象保存下来,然后再读取回来:
>>> source = """
... def hello():
... print "Hello, world!"
... """
>>>
>>> code = compile(source, '<mycustomcode>', 'exec')
>>> class Module(object): pass
...
>>> module = Module()
>>> exec code in module.__dict__
>>> module.hello()
Hello, world!
>>> import marshal
>>> marshal.dumps(code)
'c\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00@\x00\x00\x00s\r\x00\x00\x00d\
x00\x00\x84\x00\x00Z\x00\x00d\x01\x00S(\x02\x00\x00\x00c\x00\x00\x00\x00\x00\x00
\x00\x00\x01\x00\x00\x00C\x00\x00\x00s\t\x00\x00\x00d\x01\x00GHd\x00\x00S(\x02\x
00\x00\x00Ns\r\x00\x00\x00Hello, world!(\x00\x00\x00\x00(\x00\x00\x00\x00(\x00\x
00\x00\x00(\x00\x00\x00\x00s\x0e\x00\x00\x00<mycustomcode>t\x05\x00\x00\x00hello
\x02\x00\x00\x00s\x02\x00\x00\x00\x00\x01N(\x01\x00\x00\x00R\x00\x00\x00\x00(\x0
0\x00\x00\x00(\x00\x00\x00\x00(\x00\x00\x00\x00s\x0e\x00\x00\x00<mycustomcode>t\
x08\x00\x00\x00<module>\x02\x00\x00\x00s\x00\x00\x00\x00'
不过,我不太确定这是不是个好方法...
1
虽然这不是一个好的方法,但你可以只把函数里的__code__
部分进行保存...
>>> def foo():
... print "Hello"
>>> import pickle
>>> code = pickle.dumps(foo.__code__)
>>> def bar():
... pass
>>> bar()
>>> bar.__code__ = pickle.loads(code)
>>> bar()
Hello