如何可行的,它将编制Python(可能通过一个中间C表示)成机器码?

据推测这将需要链接到一条巨蟒runtime library,以及任何部分的蟒蛇的标准图书馆,这是蟒蛇自己也会需要编制(和链接)。

还有,你会需要捆绑Python解释,如果你想要做的动态评估的表达形式,但也许是一个子集,蟒蛇不能让这将仍然是有用的。

将它提供的任何速度和/或存储器使用的优势?据推测的启动时间蟒蛇的口译将被消除的(虽然公共图书馆仍将需要的装载在启动时)。

有帮助吗?

解决方案

尝试 ShedSkin Python-to-C ++编译器,但它远非完美。还有Psyco - Python JIT,如果只需要加速。但恕我直言,这不值得努力。对于速度至关重要的代码部分,最佳解决方案是将它们编写为C / C ++扩展。

其他提示

作为@格雷格Hewgill说它有很好的理由为什么这不是总是可能的。然而,某些类型的代码(如非常码算法)可以变成"真正的"机器码。

有几种选择:

  • 使用 Psyco, ,其发射机代码的动态。你应该谨慎选择哪些方法/功能转换,虽然。
  • 使用 Cython, ,这是一个巨蟒喜欢 语言汇编成一Python C扩展
  • 使用 PyPy, ,其中有一个翻译从RPython(a 受限制的子集 Python不支持某些最"动态"的特点Python)至C或编程.
    • PyPy仍然是高度实验性
    • 不是所有的扩展将本

在那之后,你可以使用一个现有的软件包(冻结,Py2exe,PyInstaller)把一切都进入一个二进制的。

所有在所有:没有任何一般性的回答你的问题。如果你有Python代码性能至关重要的,尝试使用尽可能多的系统功能的可能(或者问一个"我怎么做我的代码的更快"问题)。如果没有帮助,试图识别码和口它C(或Cython)和使用的扩展。

py2c( http://code.google.com/p/py2c )可以将python代码转换为c / C ++ 我是py2c的独立开发者。

Nuitka 是一个Python to C ++编译器,它链接到libpython。这似乎是一个相对较新的项目。作者在pystone基准测试中声称对CPython的速度提升

PyPy 一个项目,重新实现蟒蟒蛇,使编纂司机代码作为一个执行战略(其他虚拟机JIT,使用JVM,等等)。他们的汇编C版本的运行速度慢于CPython在平均水平,但远远快于一些程序。

Shedskin 是一个实验性的蟒蛇-C++编译器。

玻璃 是一个语言专门设计用于编写Python扩展的模块。它的设计之间的桥梁好的、高级别的、易于使用的世界的Python和混乱,低级别的世界。

Pyrex 是Python语言的一个子集,编译为C,由首先为Python构建列表推导的人完成。它主要是为构建包装器而开发的,但可以在更一般的环境中使用。 Cython 是一个更积极维护的派雷克斯分支。

乍一看这似乎是合理的,但是Python中有很多普通的东西不能直接映射到C表示而不需要承载很多Python运行时支持。例如,想到鸭子打字。 Python中用于读取输入的许多函数可以采用文件或类似文件的对象,只要它支持某些操作,例如。 read()或readline()。如果您考虑将此类支持映射到C所需的内容,您就会开始想象Python运行时系统已经完成的各种事情。

py2exe 等实用程序将Python程序和运行时捆绑到一个可执行文件中(目前为止)尽可能)。

一些额外参考文献:

Jython有一个针对JVM字节码的编译器。字节码是完全动态的,就像Python语言本身一样!很酷。 (是的,正如Greg Hewgill的回答所说,字节码确实使用了Jython运行时,因此Jython jar文件必须随应用程序一起分发。)

Psyco 是一种即时(JIT)编译器:Python的动态编译器,运行代码的速度提高了2-100倍,但它需要很多内存。

简而言之:它可以更快地运行您现有的Python软件,但源代码没有变化,但它不像C编译器那样编译成目标代码。

答案是“是的,有可能”。您可以使用Python代码并尝试使用CPython API将其编译为等效的C代码。事实上,曾经有一个Python2C项目就是这样,但我多年没有听说过它(回到Python 1.5天就是我上次看到它的时候。)

您可以尝试尽可能地将Python代码转换为本机C,并在需要实际Python功能时回退到CPython API。在过去的一两个月里,我一直在玩弄这个想法。然而,这是一项非常多的工作,并且大量的Python特性很难转换为C:嵌套函数,生成器,除了简单类的简单类,任何涉及从模块外部修改模块全局变量的东西,等等等等。

这不会将Python编译为机器代码。但允许创建一个共享库来调用Python代码。

如果您正在寻找的是从C运行Python代码而不依赖于execp的简单方法。您可以从python代码生成一个共享库,其中包含对 Python嵌入API 。那么应用程序就是一个共享库,你可以在许多其他库/应用程序中使用它。

这是一个创建共享库的简单示例,您可以使用C程序进行链接。共享库执行Python代码。

将要执行的python文件是 pythoncalledfromc.py

# -*- encoding:utf-8 -*-
# this file must be named "pythoncalledfrom.py"

def main(string):  # args must a string
    print "python is called from c"
    print "string sent by «c» code is:"
    print string
    print "end of «c» code input"
    return 0xc0c4  # return something

你可以尝试使用 python2 -c" import pythoncalledfromc; pythoncalledfromc.main( '你好')。它将输出:

python is called from c
string sent by «c» code is:
HELLO
end of «c» code input

共享库将由以下 callpython.h

定义
#ifndef CALL_PYTHON
#define CALL_PYTHON

void callpython_init(void);
int callpython(char ** arguments);
void callpython_finalize(void);

#endif

关联的 callpython.c 是:

// gcc `python2.7-config --ldflags` `python2.7-config --cflags` callpython.c -lpython2.7 -shared -fPIC -o callpython.so

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <python2.7/Python.h>

#include "callpython.h"

#define PYTHON_EXEC_STRING_LENGTH 52
#define PYTHON_EXEC_STRING "import pythoncalledfromc; pythoncalledfromc.main(\"%s\")"


void callpython_init(void) {
     Py_Initialize();
}

int callpython(char ** arguments) {
  int arguments_string_size = (int) strlen(*arguments);
  char * python_script_to_execute = malloc(arguments_string_size + PYTHON_EXEC_STRING_LENGTH);
  PyObject *__main__, *locals;
  PyObject * result = NULL;

  if (python_script_to_execute == NULL)
    return -1;

  __main__ = PyImport_AddModule("__main__");
  if (__main__ == NULL)
    return -1;

  locals = PyModule_GetDict(__main__);

  sprintf(python_script_to_execute, PYTHON_EXEC_STRING, *arguments);
  result = PyRun_String(python_script_to_execute, Py_file_input, locals, locals);
  if(result == NULL)
    return -1;
  return 0;
}

void callpython_finalize(void) {
  Py_Finalize();
}

您可以使用以下命令编译它:

gcc `python2.7-config --ldflags` `python2.7-config --cflags` callpython.c -lpython2.7 -shared -fPIC -o callpython.so

创建一个名为 callpythonfromc.c 的文件,其中包含以下内容:

#include "callpython.h"

int main(void) {
  char * example = "HELLO";
  callpython_init();
  callpython(&example);
  callpython_finalize();
  return 0;
}

编译并运行:

gcc callpythonfromc.c callpython.so -o callpythonfromc
PYTHONPATH=`pwd` LD_LIBRARY_PATH=`pwd` ./callpythonfromc

这是一个非常基本的例子。它可以工作,但根据库,可能仍然很难将C数据结构序列化为Python,从Python序列化为C.事情可以自动化......

Nuitka 可能是有帮助的。

此外还有 numba ,但他们都不打算完全按照您的意愿行事。可以从Python代码生成C头,但前提是您指定如何将Python类型转换为C类型或者可以推断出该信息。有关Python ast分析器的信息,请参见 python astroid

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top