As you can probably tell from the preceding overview, there is much flexibility in the embedding domain. To illustrate common embedding techniques in action, this section presents a handful of short C programs that run Python code in one form or another. Most of these examples make use of the simple Python module file shown in Example 23-1.
在前面的概覽一節中你已經知道,內嵌領域的靈活性很大。本節列舉了幾個簡短的C程序,它們以一種形式或另一種形式運行Python代碼,來演示實際的通用的內嵌技術。多數例子使用了這個簡單的Python模塊,見Example 23-1。(頭部注釋為:“C代碼以內嵌模式運行本模塊中的Python代碼。這樣一個文件可以更改而不必更改C代碼層。這只是標準的Python代碼(C代碼做轉換工作)。你也可以運行標準模塊如string中的代碼。”)
If you know any Python at all, you probably know that this file defines a string and a function; the function returns whatever it is passed with string substitution and uppercase conversions applied. It's easy to use from Python:
如果你知道一點Python,你可能知道,這個文件定義了一個字符串與一個函數;函數將輸入串替換并轉換成大寫后返回。這在Python中很容易使用:
With a little Python API wizardry, it's not much more difficult to use this module the same way in C.
利用一點Python API的魔力,在C語言中以同樣的方式使用這個模塊也不是很難。
Perhaps the simplest way to run Python code from C is by calling the PyRun_SimpleString API function. With it, C programs can execute Python programs represented as C character string arrays. This call is also very limited: all code runs in the same namespace (the module _ _main_ _), the code strings must be Python statements (not expressions), and there is no direct way to communicate inputs or outputs with the Python code run.
從C語言運行Python代碼,最簡單的方法可能是,調用PyRun_SimpleString API 函數。使用它,C程序可以執行用C字符串數組表示的Python程序。這個調用的限制也很大:所有化碼運行于同一命名空間(模塊_ _main_ _),代碼串必須是Python語句(不是表達式),也沒有直接的辦法可以與運行的Python代碼通信,進行輸入與輸出。
Still, it's a simple place to start. Moreover, when augmented with an imported C extension module that the embedded Python code can use to communicate with the enclosing C layer, this technique can satisfy many embedding goals. To demonstrate the basics, the C program in Example 23-2 runs Python code to accomplish the same results as the interactive session listed in the prior section.
但它仍是一個好的開始。另外,如果在參數中導入C擴展模塊,通過該擴展模塊,內嵌的Python代碼就可以與外面的C語言層通信了,這一技術可以滿足許多內嵌目標。C程序Example 23-2 演示了這一基本方法,它運行Python代碼,產生與上面交互式運行相同的結果。
The first thing you should notice here is that when Python is embedded, C programs always call Py_Initialize to initialize linked-in Python libraries before using any other API functions. The rest of this code is straightforwardC submits hardcoded strings to Python that are roughly what we typed interactively. Internally, PyRun_SimpleString invokes the Python compiler and interpreter to run the strings sent from C; as usual, the Python compiler is always available in systems that contain Python.
首先請注意,當Python內嵌時,在調用任何其它API函數之前,C程序總是先調用Py_Initialize,來初始化鏈接的Python庫。代碼余下部分與交互方式下打字輸入差不多,直截了當地向Python提交硬編碼的字符串。在內部,PyRun_SimpleString調用Python編譯器和解釋器,來運行C語言傳入的字符串;通常,在安裝了Python的系統上,Python編譯器總是可用的。
To build a standalone executable from this C source file, you need to link its compiled form with the Python library file. In this chapter, "library" usually means the binary library file that is generated when Python is compiled, not the Python source code library.
為了從這個C語言源文件構建獨立的執行程序,編譯后需要鏈接Python庫文件。在本章中,“庫”通常指Python編譯后生成的二進制庫文件,而不是Python源代碼庫。
Today, everything in Python that you need in C is compiled into a single Python library file when the interpreter is built (e.g., libpython2.4.dll on Cygwin). The program's main function comes from your C code, and depending on your platform and the extensions installed in your Python, you may also need to link any external libraries referenced by the Python library.
目前,當Python解釋器構建時,你在C語言中所需的所有Python的東西,會被編譯到一個Python庫文件(在Cygwin上即libpython2.4.dll)。程序的main函數來自于你的C語言代碼,與你的平臺和Python安裝的擴展有關,你可能還需要鏈接Python庫所引用的外部庫。
Assuming no extra extension libraries are needed, Example 23-3 is a minimal makefile for building the C program in Example 23-2 under Cygwin on Windows. Again, makefile details vary per platform, but see Python manuals for hints. This makefile uses the Python include-files path to find Python.h in the compile step and adds the Python library file to the final link step to make API calls available to the C program.
假設不需要額外的擴展庫,Example 23-3是在Windows的Cygwin下構建Example 23-2C程序的最小的make文件。同樣,make文件的細節隨平臺而變,請查看Python手冊獲取幫助。這個make文件在編譯時使用Python包含路徑來尋找Python.h,并在最后的鏈接步驟中添加Python庫文件,使API調用在C程序中可用。
To build a program with this file, launch make on it as usual:
用這個文件構建程序時,按通常方式運行make:
Things may not be quite this simple in practice, though, at least not without some coaxing. The makefile in Example 23-4 is the one I actually used to build all of this section's C programs on Cygwin.
但是,實際可能不這么容易,會需要一點技術。Example 23-4是我在Cygwin下實際使用的make文件,用于構建本章所有的C程序。
On some platforms, you may need to also link in other libraries because the Python library file used may have been built with external dependencies enabled and required. In fact, you may have to link in arbitrarily many more externals for your Python library, and frankly, chasing down all the linker dependencies can be tedious. Required libraries may vary per platform and Python install, so there isn't a lot of advice I can offer to make this process simple (this is C, after all). The standard C development techniques will apply.
在有些平臺上,你可能需要鏈接其它庫,因為用到的Python庫文件依賴和要求外部庫。實際上,你的Python庫可能要求你必須鏈接許多外部庫,并且坦白說,找出所有的鏈接依賴關系是很煩的。要求的庫隨平臺和安裝的Python不同而有很大不同,所以我也沒辦法使這個過程簡單點(畢竟這是C語言)。請運用標準的C語言開發技術來解決。
One thing to note is that on some platforms, if you're going to do much embedding work and you run into external dependency issues, you might want to build Python on your machine from its source with all unnecessary extensions disabled in the Modules/Setup file (or the top-level setup.py Distutils script in more recent releases). This produces a Python library with minimal external requirements, which links much more easily.
注意,在有些平臺上,如果你要做許多內嵌工作,并且你碰到了外部依賴問題,你可能需要在你的機器上,從源碼構建Python,并在Modules/Setup文件(或在新版本中的頂層setup.py Distutils腳本)中,禁用所有不必要的擴展。這樣生成的Python庫,具有最小的外部依賴,鏈接時會方便許多。
For example, if your embedded code won't be building GUIs, Tkinter can simply be removed from the library; see the README file at the top of Python's source distribution for details. You can also find a list of external libraries referenced from your Python in the generated makefiles located in the Python source tree. In any event, the good news is that you need to resolve linker dependencies only once.
例如,如果你的內嵌代碼不會構建GUI,就可以直接從庫里面移除Tkinter;詳情請參閱Python源代碼樹中頂層的README文件。在Python源代碼樹中,在生成的make文件中,你也可以找到你的Python引用外部庫的列表。無論如何,好消息是鏈接依賴問題你只需解決一次。
Once you've gotten the makefile to work, run it to build the C program with Python libraries linked in:
一旦make文件可以工作,運行它來構建C程序,并鏈接Python庫:
After building, run the resulting C program as usual, regardless of how this works in your platform:[*]
構建之后,運行生成的C程序(不同平臺方法不同[*]):
[*] Under Python 2.4 and Cygwin on Windows, I had to first set my PYTHONPATH to include the current directory in order to run the embedding examples under Python 2.4 and Cygwin, with the shell command export PYTHONPATH=.. I also had to use the shell command ./embed-simple to execute the program due to my system path setting. Your mileage may vary; if you have trouble, try running the embedded Python commands import sys and print sys.path from C to see what Python's path looks like, and take a look at the Python/C API manual for more on path configuration for embedded applications. [*]在Windows的Cygwin和Python2.4下,為了運行內嵌的例程,我必須先使用shell命令export PYTHONPATH=.,來設置PYTHONPATH包含當前目錄。同時,由于我的系統路徑設置關系,我必須使用shell命令./embed-simple來執行程序。你的方法可以不同;如果你有麻煩,試試在C語言中運行內嵌Python命令import sys和print sys.path,看看Python路徑是怎樣的,更多內嵌應用的路徑配置信息,請查閱Python/C API手冊。
[*] Under Python 2.4 and Cygwin on Windows, I had to first set my PYTHONPATH to include the current directory in order to run the embedding examples under Python 2.4 and Cygwin, with the shell command export PYTHONPATH=.. I also had to use the shell command ./embed-simple to execute the program due to my system path setting. Your mileage may vary; if you have trouble, try running the embedded Python commands import sys and print sys.path from C to see what Python's path looks like, and take a look at the Python/C API manual for more on path configuration for embedded applications.
[*]在Windows的Cygwin和Python2.4下,為了運行內嵌的例程,我必須先使用shell命令export PYTHONPATH=.,來設置PYTHONPATH包含當前目錄。同時,由于我的系統路徑設置關系,我必須使用shell命令./embed-simple來執行程序。你的方法可以不同;如果你有麻煩,試試在C語言中運行內嵌Python命令import sys和print sys.path,看看Python路徑是怎樣的,更多內嵌應用的路徑配置信息,請查閱Python/C API手冊。
Most of this output is produced by Python print statements sent from C to the linked-in Python library. It's as if C has become an interactive Python programmer.
大多數的輸出是由Python print語句產生的,該語句由C語言發送到鏈入的Python庫。就像C成為了一個交互式Python程序員。
Naturally, strings of Python code run by C probably would not be hardcoded in a C program file like this. They might instead be loaded from a text file or GUI, extracted from HTML or XML files, fetched from a persistent database or socket, and so on. With such external sources, the Python code strings that are run from C could be changed arbitrarily without having to recompile the C program that runs them. They may even be changed onsite, and by end users of a system. To make the most of code strings, though, we need to move on to more flexible API tools.
當然,C語言運行的Python代碼串,可能不是這樣在C語言文件中硬編碼的。它們可以是從一個文本文件或GUI讀取、從HTML或XML文件中提取、從數據庫或socket獲取、等等。使用這樣的外部源,就可以任意更改C語言運行的Python代碼串,而不必重新編譯運行它們的C程序。它們甚至可以由系統的最終用戶現場更改。但是,為充分利用代碼串,我們需要繼續前進,學習更靈活的API工具。
Example 23-5 uses the following API calls to run code strings that return expression results back to C:
Example 23-5使用下面的API調用來運行代碼串,并返回表達式的結果到C:
Py_Initialize
Initializes linked-in Python libraries as before
同上,初始化鏈入的Python庫
PyImport_ImportModule
Imports a Python module and returns a pointer to it
導入一個Python模塊并返回它的指針
PyModule_GetDict
Fetches a module's attribute dictionary object
獲取一個模塊的屬性字典對象
PyRun_String
Runs a string of code in explicit namespaces
在指定的名字空間內運行代碼串
PyObject_SetAttrString
Assigns an object attribute by namestring
通過namestring為一個對象的屬性賦值
PyArg_Parse
Converts a Python return value object to C form
將Python返回值對象轉換為C語言形式
The import calls are used to fetch the namespace of the usermod module listed in Example 23-1 earlier so that code strings can be run there directly (and will have access to names defined in that module without qualifications). Py_Import_ImportModule is like a Python import statement, but the imported module object is returned to C; it is not assigned to a Python variable name. As a result, it's probably more similar to the Python _ _import_ _ built-in function.
導入調用用來獲取前面Example 23-1中所列模塊usermod的名字空間,然后,代碼串就可以直接在那里運行(并且可以訪問那個模塊內定義的名字,無需修飾)。PyImport_ImportModule就像Python的import語句,但是導入的模塊對象會返回給C語言;它并不賦值給一個Python變量名。結果是,它可能更像Python的_ _import_ _內置函數。
The PyRun_String call is the one that actually runs code here, though. It takes a code string, a parser mode flag, and dictionary object pointers to serve as the global and local namespaces for running the code string. The mode flag can be Py_eval_input to run an expression, or Py_file_input to run a statement; when running an expression, the result of evaluating the expression is returned from this call (it comes back as a PyObject* object pointer). The two namespace dictionary pointer arguments allow you to distinguish global and local scopes, but they are typically passed the same dictionary such that code runs in a single namespace.[*]
而PyRun_String調用是實際運行代碼的地方。它接受一個代碼串,一個分析模式標志,和兩個字典對象指針,這兩個字典分別作為代碼串運行的全局和局部的名字空間。模式標志可以是Py_eval_input,來運行一個表達式,或者Py_file_input,來運行一個語句;當運行表達式時,這個調用會返回表達式的計算結果(返回一個對象指針PyObject*)。兩個名字空間字典指針參數允許你區分全局和局部作用域,但是它們一般是同一個字典,如此代碼會運行于單一的名字空間。[*]
(譯注:難道就不能不分表達式和語句嗎?)
[*] A related function lets you run files of code but is not demonstrated in this chapter: PyObject* PyRun_File(FILE *fp, char *filename, mode, globals, locals). Because you can always load a file's text and run it as a single code string with PyRun_String, the PyRun_File call is not always necessary. In such multiline code strings, the \n character terminates lines and indentation groups blocks as usual. [*]有一個相關的函數可以讓你運行代碼文件,但是本章沒有示例:PyObject* PyRun_File(FILE *fp, char *filename, mode, globals, locals)。因為你總是可以讀取文件內容,并作為一個代碼串,用PyRun_String來運行它,所以PyRun_File并不總是必要的。在多行代碼串的情況下,可用\n字符分隔行,并照常縮進代碼塊。
[*] A related function lets you run files of code but is not demonstrated in this chapter: PyObject* PyRun_File(FILE *fp, char *filename, mode, globals, locals). Because you can always load a file's text and run it as a single code string with PyRun_String, the PyRun_File call is not always necessary. In such multiline code strings, the \n character terminates lines and indentation groups blocks as usual.
[*]有一個相關的函數可以讓你運行代碼文件,但是本章沒有示例:PyObject* PyRun_File(FILE *fp, char *filename, mode, globals, locals)。因為你總是可以讀取文件內容,并作為一個代碼串,用PyRun_String來運行它,所以PyRun_File并不總是必要的。在多行代碼串的情況下,可用\n字符分隔行,并照常縮進代碼塊。
When compiled and run, this file produces the same result as its predecessor:
編譯后運行的結果與上個程序是一樣的:
But very different work goes into producing this output. This time, C fetches, converts, and prints the value of the Python module's message attribute directly by running a string expression and assigning a global variable (X) within the module's namespace to serve as input for a Python print statement string.
但是為了產生這個輸出,所做的工作是很不一樣的。這一次,通過運行一個字符串表達式,C語言直接獲取,轉換并打印Python模塊的message屬性,并在模塊的名字空間中,對一個全局變量(X)賦值,該變量再作為Python print語句的輸入。
Because the string execution call in this version lets you specify namespaces, you can better partition the embedded code your system runseach grouping can have a distinct namespace to avoid overwriting other groups' variables. And because this call returns a result, you can better communicate with the embedded code; expression results are outputs, and assignments to globals in the namespace in which code runs can serve as inputs.
因為該版本的字符串運行函數可以讓你指定名字空間,你可以更好地隔離系統中運行的內嵌代碼,每個代碼組都可以有一個獨特的名字空間,避免改寫其它組的變量。并且,這個函數返回一個結果,讓你可以更好地與內嵌代碼通信;表達式結果是輸出,在代碼運行的名字空間內,它又賦值給全局變量,而全局變量可以作為輸入。
Before we move on, I need to explain two coding issues here. First, this program also decrements the reference count on objects passed to it from Python, using the Py_DECREF call introduced in Chapter 22. These calls are not strictly needed here (the objects' space is reclaimed when the programs exits anyhow), but they demonstrate how embedding interfaces must manage reference counts when Python passes their ownership to C. If this was a function called from a larger system, for instance, you would generally want to decrement the count to allow Python to reclaim the objects.
在我們繼續前進前,我要解釋一下,這里有兩個代碼問題。首先,這個程序使用第22章介紹的Py_DECREF函數,減小了從Python傳來的對象的引用計數。這些調用在此并非嚴格需要(無論如何,對象占用空間在程序退出時會收回),但是它們演示了,當Python將對象所有權傳遞到C語言時,內嵌接口必須如何管理引用計數。如果這是個大型系統中的函數調用,通常你需要減小計數,以允許Python收回對象。
Second, in a realistic program, you should generally test the return values of all the API calls in this program immediately to detect errors (e.g., import failure). Error tests are omitted in this section's example to keep the code simple, but they will appear in later code listings and should be included in your programs to make them more robust.
第二,在一個實際的程序中,你一般應該立即檢查程序中所有API調用的返回值,以檢測錯誤(例如導入失敗)。本節中的例子省略了錯誤檢查,以保持代碼清晰,但是它們將會在以后的代碼清單中出現,并且應該包含在你的程序中,使之更健壯。
The last two sections dealt with running strings of code, but it's easy for C programs to deal in terms of Python objects too. Example 23-6 accomplishes the same task as Examples 23-2 and 23-5, but it uses other API tools to interact with objects in the Python module directly:
上面兩節討論的是代碼串的運行,但是對C程序來說,按Python對象運行也很容易。Example 23-6實現Examples 23-2和23-5相同的任務,但是使用其它的API工具,來與Python模塊中的對象直接交互。
Imports the module from C as before
同上,從C語言導入模塊
PyObject_GetAttrString
Fetches an object's attribute value by name
按名字獲取對象的屬性值
PyEval_CallObject
Calls a Python function (or class, or method)
調用Python的函數(或類,或方法)
Converts Python objects to C values
將Python對象轉換為C語言值
Py_BuildValue
Converts C values to Python objects
將C語言值轉換為Python對象
We met both of the data conversion functions in Chapter 22. The PyEval_CallObject call in this version of the example is the key call here: it runs the imported function with a tuple of arguments, much like the Python apply built-in function and newer func(*args) call syntax. The Python function's return value comes back to C as a PyObject*, a generic Python object pointer.
我們在第22章見過這兩個數據轉換函數。本例中的PyEval_CallObject是關鍵性的調用:它以一個元組為參數執行導入的函數,很像Python內置函數apply,或新的調用方法func(*args)。Python函數返回到C語言的返回值是一個通用的Python對象指針,PyObject*。
When compiled and run, the result is the same again:
編譯后運行的結果仍是一樣的:
But this output is generated by C this timefirst, by fetching the Python module's message attribute value, and then by fetching and calling the module's transform function object directly and printing its return value that is sent back to C. Input to the TRansform function is a function argument here, not a preset global variable. Notice that message is fetched as a module attribute this time, instead of by running its name as a code string; there is often more than one way to accomplish the same goals with different API calls.
但是這次輸出是由C語言生成的:首先,獲取Python模塊的message屬性值,然后獲取模塊的transform函數對象并直接調用,接著打印發回到C語言的返回值。這里輸入transform函數的是一個函數參數,而不是預設的全局變量。注意這次message是按模塊屬性獲取的,而不是用它的名字作為一個代碼串運行;通常有不止一個方法,可以調用不同的API,來達到相同的目的。
Running functions in modules like this is a simple way to structure embedding; code in the module file can be changed arbitrarily without having to recompile the C program that runs it. It also provides a direct communication model: inputs and outputs to Python code can take the form of function arguments and return values.
像這樣運行模塊中的函數,是構造內嵌的一個簡單的方法;模塊文件中的代碼可以任意更改,而不必重編譯運行它的C程序。它也提供了一個直接通信模式:Python代碼的輸入和輸出,可以采用函數參數和返回值的形式。
When we used PyRun_String earlier to run expressions with results, code was executed in the namespace of an existing Python module. However, sometimes it's more convenient to create a brand-new namespace for running code strings that is independent of any existing module files. The C file in Example 23-7 shows how; the new namespace is created as a new Python dictionary object, and a handful of new API calls are employed in the process:
前面我們使用PyRun_String,運行表達式并返回結果時,代碼是在現存的Python模塊的名字空間中執行的。然而,當運行一個與任何現存模塊文件都無關的代碼串時,創建一個全新的名字空間將更方便。Example 23-7的C文件顯示了該如何做;創建的新的名字空間是一個新的Python字典對象,還有,該過程中使用了幾個新的API調用:
PyDict_New
Makes a new empty dictionary object
構造一個新的空字典對象
PyDict_SetItemString
Assigns to a dictionary's key
給一個字典的鍵值賦值
PyDict_GetItemString
Fetches (indexes) a dictionary value by key
按鍵值獲取(查詢)一個字典值
Runs a code string in namespaces, as before
同上,在名字空間中運行一個代碼串
PyEval_GetBuiltins
Gets the built-in scope's module
得到內置作用域的模塊
The main trick here is the new dictionary. Inputs and outputs for the embedded code strings are mapped to this dictionary by passing it as the code's namespace dictionaries in the PyRun_String call. The net effect is that the C program in Example 23-7 works exactly like this Python code:
這里的關鍵是新建的字典。該字典作為內嵌代碼串執行的名字空間,傳遞給PyRun_String調用,代碼的輸入和輸出就都映射到了這個字典。實際效果是,Example 23-7中的C程序等同與這個Python代碼:
But here, each Python operation is replaced by a C API call.
但是這里的每一個Python操作都被替換成了C API調用。
When compiled and run, this C program creates this sort of output:
編譯運行,該C程序輸出為:
The output is different this time: it reflects the value of the Python variable X assigned by the embedded Python code strings and fetched by C. In general, C can fetch module attributes either by calling PyObject_GetAttrString with the module or by using PyDict_GetItemString to index the module's attribute dictionary (expression strings work too, but they are less direct). Here, there is no module at all, so dictionary indexing is used to access the code's namespace in C.
這次輸出不一樣:它反映了Python變量X的值,該變量由內嵌代碼串賦值,并由C語言獲取。一般來說,C語言獲取模塊屬性時,要么通過模塊調用PyObject_GetAttrString,要么使用PyDict_GetItemString來查詢模塊的屬性字典(表達式字符串也行,但是不夠直接)。這里根本沒有模塊,所以C語言使用字典查詢進入代碼的名字空間。
Besides allowing you to partition code string namespaces independent of any Python module files on the underlying system, this scheme provides a natural communication mechanism. Values that are stored in the new dictionary before code is run serve as inputs, and names assigned by the embedded code can later be fetched out of the dictionary to serve as code outputs. For instance, the variable Y in the second string run refers to a name set to 2 by C; X is assigned by the Python code and fetched later by C code as the printed result.
這個方案不僅允許你隔離代碼串的名字空間,使之不依賴于任何下層系統上的Python模塊文件,而且,它還提供了一個自然的通信機制。代碼運行前保存于新建字典中的值可以作為輸入,而內嵌代碼賦值的名字,稍后可以從字典中取出,成為輸出。例如,第二個運行的字符串中的變量Y,它所指的名字在C語言中被設為2;X由Python代碼賦值,后來被C代碼獲取,并作為結果打印。
There is one subtlety: dictionaries that serve as namespaces for running code are generally required to have a _ _builtins_ _ link to the built-in scope searched last for name lookups, set with code of this form:
有一個細微之處:運行代碼時作為名字空間的字典,一般要求具有_ _builtins_ _鍵值,它將指向內置作用域,用于名字查找,用這樣的代碼進行設置:
This is esoteric, and it is normally handled by Python internally for modules. For raw dictionaries, though, we are responsible for setting the link manually.
這有點深奧,該字典通常是由Python內部為模塊自動產生的。但是,對于原始字典,我們應負責手工設置。
When you call Python function objects from C, you are actually running the already compiled bytecode associated with the object (e.g., a function body). When running strings, Python must compile the string before running it. Because compilation is a slow process, this can be a substantial overhead if you run a code string more than once. Instead, precompile the string to a bytecode object to be run later, using the API calls illustrated in Example 23-8:[*]
當你從C語言調用Python函數對象時,你實際上是運行該對象已編譯的字節碼(例如一個函數體)。當運行字符串時,Python必須在運行它之前編譯這個字符串。因為編譯是一個費時的過程,如果你要多次運行一個代碼串,這將是可觀的開銷。不過,可以使用Example 23-8所示的API調用,將字符串預編譯為字節碼對象,然后再運行:[*]
[*] In case you've forgotten: bytecode is simply an intermediate representation for already compiled program code in the current standard Python implementation. It's a low-level binary format that can be quickly interpreted by the Python runtime system. Bytecode is usually generated automatically when you import a module, but there may be no notion of an import when running raw strings from C. [*]可能你已經忘了:在目前的標準Python實現中,程序代碼編譯后的字節碼只是一種中間代碼。它是低級的二進制格式的,可以被Python運行時系統快速解釋。字節碼通常在你導入一個模塊時自動生成,但是在C語言中運行原始字符串時,沒有導入這個概念。
[*] In case you've forgotten: bytecode is simply an intermediate representation for already compiled program code in the current standard Python implementation. It's a low-level binary format that can be quickly interpreted by the Python runtime system. Bytecode is usually generated automatically when you import a module, but there may be no notion of an import when running raw strings from C.
[*]可能你已經忘了:在目前的標準Python實現中,程序代碼編譯后的字節碼只是一種中間代碼。它是低級的二進制格式的,可以被Python運行時系統快速解釋。字節碼通常在你導入一個模塊時自動生成,但是在C語言中運行原始字符串時,沒有導入這個概念。
Py_CompileString
Compiles a string of code and returns a bytecode object
編譯一個代碼串并返回一個字節碼對象
PyEval_EvalCode
Runs a compiled bytecode object
運行一個已編譯字節碼對象
The first of these takes the mode flag that is normally passed to PyRun_String, as well as a second string argument that is used only in error messages. The second takes two namespace dictionaries. These two API calls are used in Example 23-8 to compile and execute three strings of Python code in turn.
第一個函數的第二個字符串參數僅用于出錯信息中,第三個參數是一個模式標志,與通常傳遞給PyRun_String的模式標志一樣。第二個函數接受兩個名字空間字典。Example 23-8用這兩個API調用依次編譯與執行三個Python代碼串。
This program combines a variety of techniques that we've already seen. The namespace in which the compiled code strings run, for instance, is a newly created dictionary (not an existing module object), and inputs for code strings are passed as preset variables in the namespace. When built and executed, the first part of the output is similar to previous examples in this section, but the last line represents running the same precompiled code string 11 times:
這個程序組合了我們所見過的多種技術。例如,編譯的代碼串所運行的名字空間是新建的字典(而不是已存在的模塊對象),代碼串的輸入是通過名字空間中的預設變量傳遞的。編譯執行時,輸出的第一部分與本節以前的例子類似,但最后一行是相同的預編譯代碼串運行11次的結果:
If your system executes strings multiple times, it is a major speedup to precompile to bytecode in this fashion.
如果你的系統需要多次執行字符串,以這種方式預編譯成字節碼可以大大提高速度。
Powered by: C++博客 Copyright © 金慶