Python을 머신 코드로 컴파일 할 수 있습니까?
(아마도 중간 C 표현을 통해) Python을 머신 코드로 컴파일하는 것은 얼마나 실현 가능합니까?
아마도 Python 런타임 라이브러리에 링크해야 하며 Python 자체였던 Python 표준 라이브러리의 모든 부분도 컴파일(및 링크인)해야 합니다.
또한 표현식의 동적 평가를 하려면 Python 인터프리터를 번들해야 하지만 이를 허용하지 않는 Python의 서브셋은 여전히 유용할 수 있습니다.
속도나 메모리 사용상의 이점이 있습니까?아마도 Python 인터프리터의 기동 시간은 없어질 것입니다(단, 공유 라이브러리는 기동시에 로딩할 필요가 있습니다).
SheetSkin Python-to-C++ 컴파일러를 사용해 보세요. 하지만 완벽과는 거리가 멀어요.또한 속도만 올리면 Psyco - Python JIT도 있습니다.하지만 IMHO는 노력할 가치가 없다.코드의 속도에 중요한 부분에서는 C/C++ 확장자로 기술하는 것이 가장 좋습니다.
@Greg Hewgill이 말했듯이, 이것이 항상 가능하지 않은 이유가 있습니다.그러나 특정 종류의 코드(매우 알고리즘 코드와 같은)는 "실제" 기계 코드로 변환될 수 있습니다.
몇 가지 옵션이 있습니다.
- 기계코드를 동적으로 내보내는 싸이코를 사용하세요.단, 변환할 메서드/함수를 신중하게 선택해야 합니다.
- Python C 확장자로 컴파일된 Python과 유사한 언어인 Cython을 사용합니다.
- RPython(Python의 가장 "동적인" 기능 중 일부를 지원하지 않는 Python의 제한된 부분 집합)에서 C 또는 LLVM으로 변환하는 PyPy를 사용합니다.
- PyPy는 여전히 매우 실험적입니다.
- 일부 내선번호는 표시되지 않습니다.
그 후 기존 패키지 중 하나(freeze, Py2exe, PyInstaller)를 사용하여 모든 것을 하나의 바이너리에 넣을 수 있습니다.
대체로: 당신의 질문에 대한 일반적인 답은 없습니다.퍼포먼스가 중요한 Python 코드가 있는 경우는, 가능한 한 많은 내장 기능을 사용해 주세요(또는 「How do I make make my Python code fast」의 질문).그래도 문제가 해결되지 않으면 코드를 식별하여 C(또는 Cython)에 포팅하고 확장자를 사용합니다.
Nuitka는 libpython에 대해 링크하는 Python to C++ 컴파일러입니다.비교적 새로운 프로젝트인 것 같습니다.저자는 파이스톤 벤치마크에서 CPython보다 속도가 향상되었다고 주장한다.
PyPy는 구현 전략의 하나로 네이티브 코드에 컴파일을 사용하여 Python을 Python에 재실장하는 프로젝트입니다(다른 것은 JIT를 사용하는 VM, JVM을 사용하는 등).컴파일된 C 버전은 평균 CPython보다 실행 속도가 느리지만 일부 프로그램에서는 훨씬 빠릅니다.
Shatskin은 실험적인 Python-to-C++ 컴파일러입니다.
Pyrex는 Python 확장 모듈을 작성하기 위해 특별히 설계된 언어입니다.Python의 고급스럽고 사용하기 쉬운 세계와 C의 지저분하고 낮은 세계 사이의 갭을 메우도록 설계되었습니다.
기타 참고 자료:
https://github.com/dropbox/pyston은 Dropbox에서 개발한 Python용 JIT 컴파일러입니다.
http://pythran.readthedocs.io/은 과학 컴퓨팅용 컴파일 시간 파이썬에서 C++로 변환하는 번역기입니다.
https://github.com/cosmo-ethz/hope은 과학 컴퓨팅용 JIT python에서 C++로 번역하는 도구입니다.
Pyrex는 Python 언어를 C로 컴파일하는 서브셋으로, Python을 위한 목록 컴필레이션을 최초로 구축한 사람이 실행했습니다.주로 래퍼를 빌드하기 위해 개발되었지만 보다 일반적인 컨텍스트에서 사용할 수 있습니다.시톤은 파이렉스의 더 활발하게 유지되는 포크이다.
Jython은 JVM 바이트 코드를 대상으로 하는 컴파일러를 가지고 있습니다.바이트코드는 Python 언어 자체와 마찬가지로 완전히 역동적입니다!멋있다.(네, Greg Hewgill의 답변이 시사하는 바와 같이 바이트코드는 Jython 런타임을 사용하므로 Jython jar 파일은 앱과 함께 배포해야 합니다.)
싸이코는 일종의 저스트 인 타임(JIT) 컴파일러입니다.파이썬용 다이내믹 컴파일러는 코드를 2-100배 빠르게 실행하지만 많은 메모리가 필요합니다.
즉, 소스 변경 없이 기존 Python 소프트웨어를 훨씬 더 빠르게 실행하지만 C 컴파일러와 같은 방식으로 오브젝트 코드로 컴파일되지 않습니다.
정답은 "네, 가능합니다"입니다.CPython API를 사용하여 Python 코드를 가져와 동등한 C 코드로 컴파일할 수 있습니다.사실, Python2C 프로젝트도 있었습니다만, 몇년간은 들어 본 적이 없습니다(Python 1.5일은 제가 마지막으로 본 날입니다).
가능한 한 Python 코드를 네이티브 C로 변환하고 실제 Python 기능이 필요할 때 CPython API로 폴백할 수 있습니다.나도 지난 한두 달 동안 그 아이디어를 가지고 놀았어.그러나 많은 양의 Python 기능을 C로 변환하는 것은 매우 어렵습니다. 즉, 중첩된 함수, 생성기, 단순한 메서드로 이루어진 단순한 클래스 이외의 것, 모듈 외부에서 모듈 글로벌을 수정하는 것 등입니다.
이것은 Python을 기계 코드로 컴파일하지 않습니다.그러나 Python 코드를 호출하는 공유 라이브러리를 만들 수 있습니다.
만약 당신이 찾고 있는 것이 execp에 의존하지 않고 C에서 Python 코드를 실행하는 쉬운 방법이라면.Python 임베딩 API에 대한 호출 몇 개로 둘러싸인 Python 코드에서 공유 라이브러리를 생성할 수 있습니다.어플리케이션은 공유 라이브러리이므로 다른 많은 라이브러리/어플리케이션에서 사용할 수 있습니다.
다음은 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('HELLO')
. 출력:
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 Analyzer는 Python Astroid를 참조하십시오.
언급URL : https://stackoverflow.com/questions/138521/is-it-feasible-to-compile-python-to-machine-code
'programing' 카테고리의 다른 글
Storybook의 셋업 기능을 통한 Vuex 사용 방법 (0) | 2022.09.01 |
---|---|
2개의 범용 타입을 가진 하나의 인터페이스를 구현하는 Java 클래스를 만드는 방법은 무엇입니까? (0) | 2022.09.01 |
무엇 `created()`의 Vue.js 작문 api에 있는 가치야? (0) | 2022.09.01 |
Vue.js에서 어레이 속성의 서브섹션 페이지 매기는 방법 (0) | 2022.09.01 |
Vue Router의 페이지 로드 시 "Scroll to Anchor" 시뮬레이션 방법 (0) | 2022.09.01 |