亚洲免费在线-亚洲免费在线播放-亚洲免费在线观看-亚洲免费在线观看视频-亚洲免费在线看-亚洲免费在线视频

使用C語(yǔ)言來擴(kuò)展Python程序和Zope服務(wù)器的教程

系統(tǒng) 1694 0

有幾個(gè)原因使您可能想用 C 擴(kuò)展 Zope。最可能的是您有一個(gè)已能幫您做些事的現(xiàn)成的 C 庫(kù),但是您對(duì)把它轉(zhuǎn)換成 Python 卻不感興趣。此外,由于 Python 是解釋性語(yǔ)言,所以任何被大量調(diào)用的 Python 代碼都將降低您的速度。因此,即使您已經(jīng)用 Python 寫了一些擴(kuò)展,您仍然要考慮把其中最常被調(diào)用的部分改用 C 來寫。不論哪種方式,擴(kuò)展 Zope 都是從擴(kuò)展 Python 開始。此外,擴(kuò)展 Python 會(huì)給您帶來其它的好處,因?yàn)槟拇a將可以從任何 Python 腳本訪問,而不只是從 Zope。這里唯一要提醒的是在寫本文的時(shí)候,Python 的當(dāng)前版本是 2.1,但是 Zope 仍然只能和 Python 1.5.2 一起運(yùn)行。對(duì) C 擴(kuò)展來說,兩個(gè)版本并沒有什么變化,但如果您有興趣對(duì)您的庫(kù)進(jìn)行 Python 包裝,又想讓它們都能在 Zope 下工作,您就得注意不要使用任何比 1.5.2 更新的東西。
Zope 是什么?

Zope 代表“Z Object Publishing Environment(Z 對(duì)象發(fā)布環(huán)境)”,它是用 Python 實(shí)現(xiàn)的應(yīng)用程序服務(wù)器。“太棒了,”您說,“但應(yīng)用程序服務(wù)器的確切含義是什么呢?”應(yīng)用程序服務(wù)器就是一個(gè)長(zhǎng)期運(yùn)行的進(jìn)程,它為“活動(dòng)的內(nèi)容”提供服務(wù)。Web 服務(wù)器在運(yùn)行期間調(diào)用應(yīng)用程序服務(wù)器來構(gòu)建頁(yè)面。
擴(kuò)展 Python:有趣又有益

想擴(kuò)展 Zope,您首先要擴(kuò)展 Python。雖然擴(kuò)展 Python 不像“腦外科手術(shù)”那樣復(fù)雜,但也不像“在公園中散步”那樣悠閑。有兩個(gè)基本組件用于 Python 擴(kuò)展。第一個(gè)顯然是 C 代碼。我將馬上探討它。 另一個(gè)部分是 安裝文件。安裝文件通過提供模塊名稱、模塊的 C 代碼的位置和您可能需要的所有編譯器標(biāo)志來描述模塊。該文件被預(yù)處理,以創(chuàng)建 makefile(在 UNIX 上)或 MSVC++ 工程文件(MSVC++ project file,在 Windows 上)。先說一下 ?D Windows 上的 Python 事實(shí)上是用 Microsoft 編譯器編譯的。Python.org 的人也推薦用 MSVC++ 編譯擴(kuò)展。顯然,您應(yīng)該能夠成功說服 GNU 的編譯者們,但我本人還沒試過。

無論如何,還是讓我們來定義一個(gè)叫做‘foo'的模塊吧。‘foo'模塊會(huì)有一個(gè)叫做‘bar'的函數(shù)。當(dāng)我們要使用時(shí),我們可以用 import foo; 來把這個(gè)函數(shù)導(dǎo)入到 Python 腳本中,就跟導(dǎo)入任何模塊一樣。安裝文件非常簡(jiǎn)單:
清單 1. 一個(gè)典型的安裝文件

            
# You can include comment lines. The *shared* directive indicates
# that the following module(s) are to be compiled and linked for
# dynamic loading as opposed to static: .so on Unix, .dll on Windows.
*shared*
# Then you can use the variables later using the $(variable) syntax
# that 'make' uses. This next line defines our module and tells
# Python where its source code is.
foo foomain.c


          

編寫代碼

那么我們實(shí)際上該怎樣寫 Python 知道如何使用的代碼呢,您問? foomain.c (當(dāng)然,您可以隨意命名它)文件包含三項(xiàng)內(nèi)容:一個(gè)方法表,一個(gè)初始化函數(shù)和其余的代碼。方法表簡(jiǎn)單地將函數(shù)名與函數(shù)聯(lián)系起來,并告知 Python 各個(gè)函數(shù)所使用的參數(shù)傳遞機(jī)制(您可以選擇使用一般的位置參數(shù)列表或位置參數(shù)和關(guān)鍵詞參數(shù)的混合列表)。Python 在模塊裝入時(shí)調(diào)用初始化函數(shù)。初始化函數(shù)將完成模塊所要求的所有初始化操作,但更重要的是,它還把一個(gè)指向方法表的指針傳回給 Python。

那我們就來看看我們的小型 foo 模塊的 C 代碼。
清單 2. 一個(gè)典型的 Python 擴(kuò)展模塊

            
#include 
            
              
/* Define the method table. */
static PyObject *foo_bar(PyObject *self, PyObject *args);
static PyMethodDef FooMethods[] = {
  {"bar", foo_bar, METH_VARARGS},
  {NULL, NULL}
};
/* Here's the initialization function. We don't need to do anything
  for our own needs, but Python needs that method table. */
void initfoo()
{
  (void) Py_InitModule("foo", FooMethods);
}
/* Finally, let's do something ... involved ... as an example function. */
static PyObject *foo_bar(PyObject *self, PyObject *args)
{
  char *string;
  int  len;
  if (!PyArg_ParseTuple(args, "s", &string))
    return NULL;
  len = strlen(string);
  return Py_BuildValue("i", len);
}


            
          

深入研究

我們來看會(huì)兒這些代碼。首先,請(qǐng)注意您必須包含 Python.h 。除非您已在包含路徑(include path)中設(shè)置了該文件的路徑,否則您可能需要在安裝文件中包含 -I 標(biāo)志以指向該文件。

初始化函數(shù)必須命名為 init <模塊名>,在我們的例子中是 initfoo 。初始化函數(shù)的名稱,毫無疑問,是 Python 在裝入模塊時(shí)所知道的關(guān)于模塊的全部信息,這也是初始化函數(shù)的名稱如此死板的原因。順便說一下,初始化函數(shù)必須是文件中唯一未被聲明為 static 的全局標(biāo)識(shí)符。這對(duì)靜態(tài)鏈接比對(duì)動(dòng)態(tài)鏈接更重要,因?yàn)榉?static 標(biāo)識(shí)符將是全局可見的。對(duì)動(dòng)態(tài)鏈接來說,這不是一個(gè)很大的問題,但如果您打算在編譯期間鏈接所有東西,又沒有把所有可以聲明為 static 的東西聲明為 static ,那么您很可能就會(huì)碰到名稱沖突的問題。

現(xiàn)在我們來觀察實(shí)際的代碼,看看參數(shù)是怎樣被處理的,返回值又是怎樣被傳遞的。當(dāng)然,一切都是 PyObject ?D Python 堆上的對(duì)象。您從參數(shù)中得到的是一個(gè)對(duì)“this”對(duì)象的引用(this 用于對(duì)象方法,對(duì)類似 bar() 這樣的無參數(shù)的老式函數(shù)來說是 NULL)和一個(gè)存儲(chǔ)在 args 中的參數(shù)元組。您用 PyArg_ParseTuple 找回您的參數(shù),然后用 Py_BuildValue 把結(jié)果傳回去。這些函數(shù)(還有更多)都?xì)w檔在 Python 文檔的“Python/C API”部分中。不幸的是,沒有按名稱排列的簡(jiǎn)單的函數(shù)清單,文檔是按主題排列的。

另請(qǐng)注意,函數(shù)在出錯(cuò)的情況下返回 NULL。返回 NULL 表示出錯(cuò)了;如果想讓 Python 做得更好,您應(yīng)該拋出異常。我會(huì)指點(diǎn)您去查閱關(guān)于如何做這件事的文檔。

編譯擴(kuò)展

現(xiàn)在剩下的全部問題是編譯模塊。您可以通過兩種方式進(jìn)行。第一種是按照文檔中的指導(dǎo),運(yùn)行 make -f Makefile.pre.in boot ,這樣將會(huì)使用您的 Setup 來編譯一個(gè) Makefile。然后您就用該 Makefile 編譯您的工程。這種方式只適用于 UNIX。對(duì) Windows 來說,存在一個(gè)叫“compile.py”的腳本(請(qǐng)參閱本文后面的 參考資料)。原始腳本很難找到;我從一個(gè)郵件列表中找到了一個(gè)來自 Robin Dunn(wxPython 的幕后工作者)的被大量改動(dòng)了的副本。這個(gè)腳本能在 UNIX 和 Windows 上工作;在 Windows 上,它將從您的 Setup 開始編譯 MSVC++ 工程文件。

要進(jìn)行編譯,您必須使包含的文件和庫(kù)都可用。Python 的標(biāo)準(zhǔn) Zope 安裝沒有包含這些文件,因此您需要從 www.python.org(請(qǐng)參閱 參考資料)安裝 Python 的常規(guī)安裝。在 Windows 上,您還必須從源代碼安裝的 PC 目錄中獲取 config.h 文件;它是 UNIX 安裝為您編譯的 config.h 的手工版。因此,在 UNIX 上,您應(yīng)該已經(jīng)擁有它了。

一旦這些都完成后,您就會(huì)得到一個(gè)以“.pyd”為擴(kuò)展名的文件。把這個(gè)文件放到 Python 安裝目錄下的“l(fā)ib”目錄(在 Zope 下,Python 位于“bin”目錄,因此您的擴(kuò)展得結(jié)束于“bin/lib”目錄,奇怪吧。)然后您就可以調(diào)用它了,就像調(diào)用任何源生的 Python 模塊一樣。

            
 >>> import foo;
 >>> foo.bar ("This is a test");
 14


          

做到這里時(shí),我的第一個(gè)問題是問自己該如何用 C 定義從 Python 中可見的 類。事實(shí)上,我可能問了一個(gè)錯(cuò)誤的問題。在我已研究的示例中,特定于 Python 的一切都只 用 Python 來完成,也都只調(diào)用從您的擴(kuò)展中導(dǎo)出的 C 函數(shù)。

把它帶到 Zope 中去

一旦完成了您的 Python 擴(kuò)展,下一步就是使 Zope 能和它一起工作。您有幾種方式可以選擇,但在一定程度上,您希望您的擴(kuò)展以什么方式與 Zope 一起工作將首先影響到您編譯擴(kuò)展的方式。從 Zope 內(nèi)使用 Python(以及用 C 所做的擴(kuò)展)代碼的基本方式是:

  • ??? 如果函數(shù)很簡(jiǎn)單,您可以把它當(dāng)作一個(gè)變量。這些被叫做“外部方法”。
  • ??? 更復(fù)雜的類,可以從 Zope 腳本中調(diào)用(這是 Zope 2.3 的一個(gè)新功能)。
  • ??? 您可以定義一個(gè) Zope Product,然后可以用 ZClass(一組已做好的、Web 可訪問的對(duì)象)擴(kuò)展它,在腳本中使用它,根據(jù)它的自有權(quán)限發(fā)布它(它的實(shí)例被當(dāng)作頁(yè)來對(duì)待)。

當(dāng)然,您自己的應(yīng)用程序可以使用這些方式的組合。

創(chuàng)建外部方法

從 Zope 調(diào)用 Python 的最簡(jiǎn)單的方式是把您的 Python 代碼做成 外部方法。外部方法是被放到 Zope 安裝目錄下的“Extensions”目錄中的 Python 函數(shù)。一旦那里有了這樣一個(gè) Python 文件,您就可以轉(zhuǎn)到任意文件夾,選擇“添加外部方法”,并添加調(diào)用要使用的函數(shù)的變量。然后您就可以往該文件夾中顯示調(diào)用結(jié)果的任意頁(yè)添加 DTML 字段。我們來看一個(gè)使用了上面所定義的 Python 擴(kuò)展 ?D foo.bar ?D 的簡(jiǎn)單示例。

首先,來看擴(kuò)展本身:我們把它放到一個(gè)例如叫 foo.pyd 的文件中。記住,這個(gè)文件位于 Zope 下的 Extensions 目錄。為了能夠順利進(jìn)行,當(dāng)然,我們?cè)谏厦鎰?chuàng)建的 foo.pyd 必須在位于 bin/lib 的 Python 庫(kù)中。一個(gè)出于這個(gè)目的的、簡(jiǎn)單的包看起來可能像這樣:
清單 3. 一個(gè)簡(jiǎn)單的外部方法(文件:Extensions/foo.py)

            
import foo
def bar(self,arg):
  """A simple external method."""
  return 'Arg length: %d' % foo.bar(arg)


          

很簡(jiǎn)單,不是嗎?它定義了一個(gè)可以用 Zope 管理界面附加到任意文件夾的外部方法“bar”。要從該文件夾中的任何頁(yè)中調(diào)用我們的擴(kuò)展,我們只需簡(jiǎn)單地插入一個(gè) DTML 變量引用,如下所示:

            
            
          

當(dāng)用戶查看我們的頁(yè)時(shí),DTML 字段將被文本“Arg length: 14”代替。我們就這樣用 C 擴(kuò)展了 Zope。

Zope 腳本:Cliff Notes 版

Zope 腳本是 Python 2.3 的一個(gè)想用來代替外部方法的新功能。外部方法能做到的,它都能做到,而且它能和安全性及管理系統(tǒng)更好地集成,在集成方面提供更多的靈活性,它還有很多對(duì) Zope API 中公開的全部 Zope 功能的訪問。

一個(gè)腳本基本上就是一個(gè)短小的 Python 程序。它可以定義類或函數(shù),但不是必須的。它被作為對(duì)象安裝在 Zope 文件夾中,然后就可以把它當(dāng)作 DTML 變量或調(diào)用(就像一個(gè)外部方法)來調(diào)用或者“從 Web 中”(在 Zope 中的意思就是它將被當(dāng)作頁(yè)來調(diào)用)調(diào)用它。當(dāng)然,這意味著腳本可以像 CGI 程序那樣生成對(duì)表單提交的響應(yīng),但卻沒有 CGI 的開銷。確實(shí)是一個(gè)很棒的功能。此外,腳本有權(quán)訪問被調(diào)用者或調(diào)用者對(duì)象(通過“context”對(duì)象)、對(duì)象所在的文件夾(通過“container”對(duì)象)和其他一些零碎信息。要獲得更多關(guān)于腳本的知識(shí),請(qǐng)參閱 Zope 手冊(cè)(請(qǐng)參閱 參考資料)中的“高級(jí) Zope 腳本編制(Advanced Zope Scripting)”那一章。

您可能會(huì)錯(cuò)誤地認(rèn)為可以直接從腳本簡(jiǎn)單地導(dǎo)入 foo 并使用 foo.bar(我知道我確實(shí)犯過這種錯(cuò)誤)。但事實(shí)并非如此。由于安全性限制,只有 Product 可以被導(dǎo)入,而不是什么模塊都可以。一般而言,Zope 的設(shè)計(jì)者們認(rèn)為任何腳本編制都需要訪問文件系統(tǒng),既然腳本對(duì)象是由 Web 使用 Zope 管理界面來管理,所以它們不是完全可信的。所以我打算就此打住,不給您展示示例腳本了,而是來討論 Product 和基礎(chǔ)類。

專注于 Product

Product 是擴(kuò)展 Zope 的強(qiáng)大工具方法。從安裝目錄的級(jí)別來看,Product 就是位于 Zope 目錄下的“l(fā)ib/python/Products”目錄中的一個(gè)目錄。在您自己的 Zope 安裝目錄中,您可以看到很多 product 示例,但本質(zhì)上,最小的 Product 只由位于該目錄的兩個(gè)文件組成:一個(gè)可任意命名的代碼文件和一個(gè) Zope 在啟動(dòng)時(shí)調(diào)用來初始化 Product 的稱為 __init__.py 的文件。(請(qǐng)注意:Zope 只在啟動(dòng)時(shí)讀取 Product 文件,這意味著為了測(cè)試,您必須能夠停止和重新啟動(dòng) Zope 進(jìn)程)。本文只是盡量多提供一些您能通過使用 Zope Product 做到的事的提示。

要知道的是 Product 封裝了一個(gè)或多個(gè)可從 ZClass、腳本或直接從 Web 上的 URL 使用的類。(當(dāng)然,在最后一種情況下,Product 的實(shí)例被當(dāng)作文件夾看待;那么 URL 的最后部分指定了將被調(diào)用的方法,該方法返回任意的 HTML。)您不必一定要把 Product 當(dāng)作“可添加的”對(duì)象來對(duì)待,雖然這是它的主要目的。要看一個(gè)優(yōu)秀的、現(xiàn)實(shí)存在的示例,可以去看 ZCatalog 實(shí)現(xiàn),它是標(biāo)準(zhǔn) Zope 分發(fā)的一部分。那里您可以在 __init__.py 中看到一個(gè)非常簡(jiǎn)單的安裝腳本,可以在 ZCatalog.py 中看到 ZCatalog 類,該類提供了很多發(fā)布方法。請(qǐng)注意 Zope 采用一種奇怪的約定來確定哪些方法可以通過 Web 訪問 ?D 如果一個(gè)方法包含有一個(gè) doc 字符串,那么該方法可通過 Web 訪問;否則,就被認(rèn)為是私有的。

無論如何,我們還是來看一個(gè)使用了 C 模塊(我們?cè)谏厦娑x了它)的非常簡(jiǎn)單的 Product。首先來看非常簡(jiǎn)單的 __init__.py;請(qǐng)注意它只做了一件事,即告訴 Zope 我們正在安裝的類的名稱。更復(fù)雜的初始化腳本能做 更多的事,包括聲明由服務(wù)器維護(hù)的全局變量以及設(shè)置訪問權(quán)限等等。欲了解更多詳細(xì)信息,請(qǐng)參閱在線文檔中的 Zope 開發(fā)者指南,也請(qǐng)研究您的 Zope 安裝目錄中現(xiàn)成的 Product。您或許已經(jīng)猜到了,我們的示例 Product 被稱為“Foo”。這樣您就將在 lib/python/Products 目錄下創(chuàng)建一個(gè) Foo 子目錄。
清單 4. 基本的 Product 初始化腳本

            
import Foo
def initialize(context):
  context.registerClass(
    Foo.Foo, 
    permission='Add Foo',
    constructors=Foo.manage_addFoo
    )


          

現(xiàn)在請(qǐng)注意這個(gè)初始化腳本不僅導(dǎo)入了那個(gè)類,使它可被 Zope 的其它部件訪問,而且還將該類注冊(cè)成具有“可添加性”。 context.registerClass 調(diào)用通過首先命名我們所導(dǎo)入的類,然后指定可被用于添加實(shí)例的方法名稱(這個(gè)方法必須顯示一個(gè)管理頁(yè)面,且該方法將自動(dòng)與 Zope 管理界面集成)的名稱來完成這項(xiàng)工作。酷。

我們來小結(jié)一下這個(gè)短小、簡(jiǎn)單的 Product。它會(huì)把我們的 foo.bar 函數(shù)公開給腳本和 ZClass,并且還有一個(gè)作為“可添加的”對(duì)象的小接口,這就是全部?jī)?nèi)容。
清單 5. 一個(gè)簡(jiǎn)單的 Zope Product

            
import foo
class Foo(SimpleItem.Item):
 "A Foo Product"
 meta_type = 'foo'
 def bar(self, string):
   return foo.bar(string)
 def __init__(self, id):
   "Initialize an instance"
   self.id = id
 def index_html(self):
   "Basic view of object"
   return '
My id is %s and its length is %d.
' % (self.id, foo.bar(self.id))
 def manage_addFoo(self, RESPONSE):
   "Management handler to add an instance to a folder."
   self._setObject('Foo_id', Foo('Foo_id'))
   RESPONSE.redirect('index_html')


          

這只是一個(gè)最簡(jiǎn)單的 Product。不能絕對(duì)地說它是可能的 Product 中最小的一個(gè),但已經(jīng)很接近了。不過,它確實(shí)說明了 Product 的一些關(guān)鍵特征。首先,請(qǐng)注意“index_html”方法:它被調(diào)用來顯示一個(gè)對(duì)象實(shí)例,這是通過構(gòu)建 HTML 完成的。它實(shí)際上是一個(gè)頁(yè)面。 manage_addFoo 方法是 Zope 對(duì)象管理的接口;我們?cè)谏厦娴?__init__.py 中引用了它。“__init__”方法初始化對(duì)象;實(shí)際上它 必須做的全部工作就是記錄實(shí)例的唯一標(biāo)識(shí)符。

這個(gè)微型的 Product 不和 Zope 安全性進(jìn)行交互操作。它不做很多管理工作。它沒有交互功能。所以您可以給它添加很多東西(甚至連很有用的功能它也沒有)。我希望這對(duì)您是一個(gè)很好的開始。

以后該做什么

對(duì) Zope Product 的簡(jiǎn)單介紹已經(jīng)告訴您如何把 C 語(yǔ)言函數(shù)從 C 代碼變?yōu)?Zope 中可用的。要學(xué)會(huì)怎么寫 Product,您還得閱讀更多文檔(其中有很多仍在完善之中),坦率地說,還要研究已有的 Product,看看它們是怎么做的。Zope 模型有很強(qiáng)大的功能和很大的靈活性,它們都很值得探究。

我目前正在做集成 C 和 Zope 的大工程:集成我的工作流工具包(workflow toolkit)。在本文發(fā)表之前,我希望能看到它的雛形。它已被列在下面的參考資料中,去看看吧;到您閱讀本文時(shí),應(yīng)該已經(jīng)能夠從中找到一個(gè)擴(kuò)展示例。祝我好運(yùn)。


更多文章、技術(shù)交流、商務(wù)合作、聯(lián)系博主

微信掃碼或搜索:z360901061

微信掃一掃加我為好友

QQ號(hào)聯(lián)系: 360901061

您的支持是博主寫作最大的動(dòng)力,如果您喜歡我的文章,感覺我的文章對(duì)您有幫助,請(qǐng)用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點(diǎn)擊下面給點(diǎn)支持吧,站長(zhǎng)非常感激您!手機(jī)微信長(zhǎng)按不能支付解決辦法:請(qǐng)將微信支付二維碼保存到相冊(cè),切換到微信,然后點(diǎn)擊微信右上角掃一掃功能,選擇支付二維碼完成支付。

【本文對(duì)您有幫助就好】

您的支持是博主寫作最大的動(dòng)力,如果您喜歡我的文章,感覺我的文章對(duì)您有幫助,請(qǐng)用微信掃描上面二維碼支持博主2元、5元、10元、自定義金額等您想捐的金額吧,站長(zhǎng)會(huì)非常 感謝您的哦!!!

發(fā)表我的評(píng)論
最新評(píng)論 總共0條評(píng)論
主站蜘蛛池模板: 日日撸夜夜干 | 国产精品免费播放 | 天天干夜夜怕 | 中文字幕日韩欧美一区二区三区 | 日本中文字幕高清 | 99视频网址 | 久久精品免费视频6 | 狠狠操狠狠插 | 亚洲视频中文字幕在线 | 快播视频在线 | 91在线永久 | 男女污污在线观看 | 97视频免费在线观看 | 奇米影视四色中文字幕 | 色涩播| 99久9在线 | 免费 | 一区二区三区四区五区 | 午夜视频福利在线 | 亚洲 国产 路线1路线2路线 | 久久99精品久久久久久水蜜桃 | 久久精品re| 天天躁日日2018躁狠狠躁 | 一级毛片网| 国语毛片| 日本aaaaa级毛片 | 精精国产www视频在线观看免费 | 国产精品亚洲国产 | 四虎永久在线精品2022 | 淫视频网站 | 久久久久久噜噜噜久久久精品 | 成人影院免费在线观看 | 精品爱爱| 日韩 欧美 | 亚洲婷婷在线 | 真人毛片免费拍拍拍aa视频 | 免费视频爰爱太爽了 | 日韩一区二区三区在线观看 | 大学生久久香蕉国产线看观看 | 中文字幕精品视频在线观 | 国内精品久久久久影院免费 | 91麻豆精品一二三区在线 |