我有一个专门为Python编写的纯C模块,我想通过使用“python -m 模块名”方法来调用它。对于用Python实现的模块,这种方法可以正常工作,其中一个明显的解决方法是添加一个额外的文件来完成这个目的。然而,我真的希望将所有内容都保留在一个单独的分发二进制文件中,而不是为此添加第二个文件。
我不在乎解决方案有多么巧妙。
如果您尝试使用-m选项加载一个C模块,则会收到错误消息No code object available for <modulename>
。
我有一个专门为Python编写的纯C模块,我想通过使用“python -m 模块名”方法来调用它。对于用Python实现的模块,这种方法可以正常工作,其中一个明显的解决方法是添加一个额外的文件来完成这个目的。然而,我真的希望将所有内容都保留在一个单独的分发二进制文件中,而不是为此添加第二个文件。
我不在乎解决方案有多么巧妙。
如果您尝试使用-m选项加载一个C模块,则会收到错误消息No code object available for <modulename>
。
-m
实现在 runpy._run_module_as_main
中。其本质是:
mod_name, loader, code, fname = _get_module_details(mod_name)
<...>
exec code in run_globals
编译模块没有与之关联的“代码对象”,因此第一条语句会出现错误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
调用的内部函数,并且可以自信地说,它们甚至不会尝试从类型为 imp.PY_SOURCE
、imp.PY_COMPILED
或 imp.PKG_DIRECTORY
的模块中检索代码对象。因此,您必须以这种或那种方式修补此机制,以使 -m
起作用。Python 在从您的模块检索任何内容之前就失败了(它甚至不检查 dll 是否为有效模块),因此您无法通过特殊方式构建来实现任何东西。
python -m app.module
? - HereHere你的单一分布式二进制需求是否允许使用egg?如果是这样,你可以将你的模块与一个包含调用代码和通常的__init__.py的__main__.py打包...
如果你非常坚持,也许你可以扩展pkgutil.ImpLoader.get_code以返回C模块的内容(例如,可能是一个特殊的__code__函数)。为了做到这一点,我认为你必须实际上在Python源代码中进行更改。即使如此,pkgutil仍然使用exec来执行代码块,因此它仍然需要Python代码。
简而言之:我认为你被卡住了。虽然Python模块在导入时具有在全局级别运行的代码,但C模块没有;它们大多只是一个字典命名空间。因此,从概念上讲,运行C模块并没有太多意义。你需要一些真正的Python代码来指导操作。
python -c "import module;module.main()"
或者创建一个只包含这 4 个单词的 .py 文件。 - Roger Binns我认为你需要从在Python中创建一个单独的文件开始,然后让-m选项起作用。然后将这个Python文件转换成一个代码对象,并以这样一种方式将它合并到你的二进制代码中,使得它继续工作。
在PyPi中查找setuptools,下载.egg文件并查看文件。你会发现前面几个字节包含了一个Python脚本,这些脚本后面跟着一个.ZIP文件字节流。类似的方法也可能适用于你。
有一个全新的东西可以轻松解决你的问题。我刚刚了解到它,看起来相当不错:http://code.google.com/p/pts-mini-gpl/wiki/StaticPython