我有一个用于Python的纯C模块,我希望能够使用python -m modulename
方法调用它。这适用于使用Python实现的模块,一个明显的解决方法是为此目的添加额外的文件。但是我真的希望将内容保存到我的单个分布式二进制文件中,而不是为此解决方法添加第二个文件。
我不在乎解决方案有多糟糕。
如果您尝试将-c模块与-m一起使用,则会收到错误消息No code object available for <modulename>
。
答案 0 :(得分:2)
-m
实施位于runpy._run_module_as_main
。其实质是:
mod_name, loader, code, fname = _get_module_details(mod_name)
<...>
exec code in run_globals
已编译的模块没有与之关联的“代码对象”,因此第1个语句失败并显示ImportError("No code object available for <module>")
。您需要扩展runpy - 特别是_get_module_details
- 以使其适用于已编译的模块。我建议返回一个由上述"import mod; mod.main()"
构造的代码对象:
(python 2.6.1)
code = loader.get_code(mod_name)
if code is None:
+ if loader.etc[2]==imp.C_EXTENSION:
+ code=compile("import %(mod)s; %(mod)s.main()"%{'mod':mod_name},"<extension loader wrapper>","exec")
+ else:
+ raise ImportError("No code object available for %s" % mod_name)
- raise ImportError("No code object available for %s" % mod_name)
filename = _get_filename(loader, mod_name)
(更新:修复了格式字符串中的错误)
现在...
C:\Documents and Settings\Пользователь>python -m pythoncom
C:\Documents and Settings\Пользователь>
这仍然不适用于内置模块。同样,你需要为他们发明一些“主代码单元”的概念。
更新
我查看了来自_get_module_details
的内部信息,可以放心地说,他们甚至没有尝试从{{{em>以外的类型的模块中检索代码对象1}},imp.PY_SOURCE
或imp.PY_COMPILED
。因此,您 以这种方式修补此机制,以便imp.PKG_DIRECTORY
能够正常工作。在从模块中检索任何内容之前,Python失败了(它甚至不检查dll是否是一个有效的模块)所以你不能通过在特殊模块中构建它来做任何事情方式。
答案 1 :(得分:0)
您对单个分布式二进制文件的要求是否允许使用鸡蛋?如果是这样,您可以使用__main__.py
打包您的模块,其中包含您的调用代码和通常的__init__.py
...
如果你非常坚持,也许你可以扩展pkgutil.ImpLoader.get_code
以返回C模块的内容(例如,可能是一个特殊的__code__
函数)。要做到这一点,我认为你将不得不在Python源代码中实际更改它。即便如此,pkgutil
使用exec
来执行代码块,所以无论如何它都必须是Python代码。
TL; DR:我想你真的很高兴。虽然Python模块在导入时运行的全局级别具有代码,但C模块却没有;它们大多只是一个dict命名空间。因此,从概念的角度来看,运行C模块并没有多大意义。您需要一些真正的Python代码来指导操作。
答案 2 :(得分:-1)
我认为您需要首先在Python中创建一个单独的文件并使-m选项起作用。然后,将该Python文件转换为代码对象,并将其合并到二进制文件中,使其继续工作。
在PyPi中查找setuptools,下载.egg并查看该文件。您将看到前几个字节包含一个Python脚本,后面跟着一个.ZIP文件字节流。类似的东西可能适合你。
答案 3 :(得分:-1)
有一种全新的东西可以轻松解决您的问题。我刚刚了解了它,它看起来对我很好:http://code.google.com/p/pts-mini-gpl/wiki/StaticPython