使用C語(yǔ)言來(lái)擴(kuò)展Python程序和Zope服務(wù)器的教程
有幾個(gè)原因使您可能想用 C 擴(kuò)展 Zope。最可能的是您有一個(gè)已能幫您做些事的現(xiàn)成的 C 庫(kù),但是您對(duì)把它轉(zhuǎn)換成 Python 卻不感興趣。此外,由于 Python 是解釋性語(yǔ)言,所以任何被大量調(diào)用的 Python 代碼都將降低您的速度。因此,即使您已經(jīng)用 Python 寫(xiě)了一些擴(kuò)展,您仍然要考慮把其中最常被調(diào)用的部分改用 C 來(lái)寫(xiě)。不論哪種方式,擴(kuò)展 Zope 都是從擴(kuò)展 Python 開(kāi)始。此外,擴(kuò)展 Python 會(huì)給您帶來(lái)其它的好處,因?yàn)槟拇a將可以從任何 Python 腳本訪(fǎng)問(wèn),而不只是從 Zope。這里唯一要提醒的是在寫(xiě)本文的時(shí)候,Python 的當(dāng)前版本是 2.1,但是 Zope 仍然只能和 Python 1.5.2 一起運(yùn)行。對(duì) C 擴(kuò)展來(lái)說(shuō),兩個(gè)版本并沒(méi)有什么變化,但如果您有興趣對(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ù)器?!疤袅?,”您說(shuō),“但應(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ù)器來(lái)構(gòu)建頁(yè)面。
擴(kuò)展 Python:有趣又有益
想擴(kuò)展 Zope,您首先要擴(kuò)展 Python。雖然擴(kuò)展 Python 不像“腦外科手術(shù)”那樣復(fù)雜,但也不像“在公園中散步”那樣悠閑。有兩個(gè)基本組件用于 Python 擴(kuò)展。第一個(gè)顯然是 C 代碼。我將馬上探討它。 另一個(gè)部分是 安裝文件。安裝文件通過(guò)提供模塊名稱(chēng)、模塊的 C 代碼的位置和您可能需要的所有編譯器標(biāo)志來(lái)描述模塊。該文件被預(yù)處理,以創(chuàng)建 makefile(在 UNIX 上)或 MSVC++ 工程文件(MSVC++ project file,在 Windows 上)。先說(shuō)一下 ― Windows 上的 Python 事實(shí)上是用 Microsoft 編譯器編譯的。Python.org 的人也推薦用 MSVC++ 編譯擴(kuò)展。顯然,您應(yīng)該能夠成功說(shuō)服 GNU 的編譯者們,但我本人還沒(méi)試過(guò)。
無(wú)論如何,還是讓我們來(lái)定義一個(gè)叫做‘foo'的模塊吧。‘foo'模塊會(huì)有一個(gè)叫做‘bar'的函數(shù)。當(dāng)我們要使用時(shí),我們可以用 import foo; 來(lái)把這個(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
編寫(xiě)代碼
那么我們實(shí)際上該怎樣寫(xiě) Python 知道如何使用的代碼呢,您問(wèn)? foomain.c (當(dāng)然,您可以隨意命名它)文件包含三項(xiàng)內(nèi)容:一個(gè)方法表,一個(gè)初始化函數(shù)和其余的代碼。方法表簡(jiǎn)單地將函數(shù)名與函數(shù)聯(lián)系起來(lái),并告知 Python 各個(gè)函數(shù)所使用的參數(shù)傳遞機(jī)制(您可以選擇使用一般的位置參數(shù)列表或位置參數(shù)和關(guān)鍵詞參數(shù)的混合列表)。Python 在模塊裝入時(shí)調(diào)用初始化函數(shù)。初始化函數(shù)將完成模塊所要求的所有初始化操作,但更重要的是,它還把一個(gè)指向方法表的指針傳回給 Python。
那我們就來(lái)看看我們的小型 foo 模塊的 C 代碼。
清單 2. 一個(gè)典型的 Python 擴(kuò)展模塊
#include <Python.h> /* 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); }
深入研究
我們來(lái)看會(huì)兒這些代碼。首先,請(qǐng)注意您必須包含 Python.h 。除非您已在包含路徑(include path)中設(shè)置了該文件的路徑,否則您可能需要在安裝文件中包含 -I 標(biāo)志以指向該文件。
初始化函數(shù)必須命名為 init <模塊名>,在我們的例子中是 initfoo 。初始化函數(shù)的名稱(chēng),毫無(wú)疑問(wèn),是 Python 在裝入模塊時(shí)所知道的關(guān)于模塊的全部信息,這也是初始化函數(shù)的名稱(chēng)如此死板的原因。順便說(shuō)一下,初始化函數(shù)必須是文件中唯一未被聲明為 static 的全局標(biāo)識(shí)符。這對(duì)靜態(tài)鏈接比對(duì)動(dòng)態(tài)鏈接更重要,因?yàn)榉?static 標(biāo)識(shí)符將是全局可見(jiàn)的。對(duì)動(dòng)態(tài)鏈接來(lái)說(shuō),這不是一個(gè)很大的問(wèn)題,但如果您打算在編譯期間鏈接所有東西,又沒(méi)有把所有可以聲明為 static 的東西聲明為 static ,那么您很可能就會(huì)碰到名稱(chēng)沖突的問(wèn)題。
現(xiàn)在我們來(lái)觀(guān)察實(shí)際的代碼,看看參數(shù)是怎樣被處理的,返回值又是怎樣被傳遞的。當(dāng)然,一切都是 PyObject ― Python 堆上的對(duì)象。您從參數(shù)中得到的是一個(gè)對(duì)“this”對(duì)象的引用(this 用于對(duì)象方法,對(duì)類(lèi)似 bar() 這樣的無(wú)參數(shù)的老式函數(shù)來(lái)說(shuō)是 NULL)和一個(gè)存儲(chǔ)在 args 中的參數(shù)元組。您用 PyArg_ParseTuple 找回您的參數(shù),然后用 Py_BuildValue 把結(jié)果傳回去。這些函數(shù)(還有更多)都?xì)w檔在 Python 文檔的“Python/C API”部分中。不幸的是,沒(méi)有按名稱(chēng)排列的簡(jiǎn)單的函數(shù)清單,文檔是按主題排列的。
另請(qǐng)注意,函數(shù)在出錯(cuò)的情況下返回 NULL。返回 NULL 表示出錯(cuò)了;如果想讓 Python 做得更好,您應(yīng)該拋出異常。我會(huì)指點(diǎn)您去查閱關(guān)于如何做這件事的文檔。
編譯擴(kuò)展
現(xiàn)在剩下的全部問(wèn)題是編譯模塊。您可以通過(guò)兩種方式進(jìn)行。第一種是按照文檔中的指導(dǎo),運(yùn)行 make -f Makefile.pre.in boot ,這樣將會(huì)使用您的 Setup 來(lái)編譯一個(gè) Makefile。然后您就用該 Makefile 編譯您的工程。這種方式只適用于 UNIX。對(duì) Windows 來(lái)說(shuō),存在一個(gè)叫“compile.py”的腳本(請(qǐng)參閱本文后面的 參考資料)。原始腳本很難找到;我從一個(gè)郵件列表中找到了一個(gè)來(lái)自 Robin Dunn(wxPython 的幕后工作者)的被大量改動(dòng)了的副本。這個(gè)腳本能在 UNIX 和 Windows 上工作;在 Windows 上,它將從您的 Setup 開(kāi)始編譯 MSVC++ 工程文件。
要進(jìn)行編譯,您必須使包含的文件和庫(kù)都可用。Python 的標(biāo)準(zhǔn) Zope 安裝沒(méi)有包含這些文件,因此您需要從 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è)問(wèn)題是問(wèn)自己該如何用 C 定義從 Python 中可見(jiàn)的 類(lèi)。事實(shí)上,我可能問(wèn)了一個(gè)錯(cuò)誤的問(wèn)題。在我已研究的示例中,特定于 Python 的一切都只 用 Python 來(lái)完成,也都只調(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ù)雜的類(lèi),可以從 Zope 腳本中調(diào)用(這是 Zope 2.3 的一個(gè)新功能)。
- 您可以定義一個(gè) Zope Product,然后可以用 ZClass(一組已做好的、Web 可訪(fǎng)問(wèn)的對(duì)象)擴(kuò)展它,在腳本中使用它,根據(jù)它的自有權(quán)限發(fā)布它(它的實(shí)例被當(dāng)作頁(yè)來(lái)對(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 字段。我們來(lái)看一個(gè)使用了上面所定義的 Python 擴(kuò)展 ― foo.bar ― 的簡(jiǎn)單示例。
首先,來(lái)看擴(kuò)展本身:我們把它放到一個(gè)例如叫 foo.pyd 的文件中。記住,這個(gè)文件位于 Zope 下的 Extensions 目錄。為了能夠順利進(jìn)行,當(dāng)然,我們?cè)谏厦鎰?chuàng)建的 foo.pyd 必須在位于 bin/lib 的 Python 庫(kù)中。一個(gè)出于這個(gè)目的的、簡(jiǎn)單的包看起來(lái)可能像這樣:
清單 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 變量引用,如下所示:
<dtml-var bar('This is a test')>
當(dāng)用戶(hù)查看我們的頁(yè)時(shí),DTML 字段將被文本“Arg length: 14”代替。我們就這樣用 C 擴(kuò)展了 Zope。
Zope 腳本:Cliff Notes 版
Zope 腳本是 Python 2.3 的一個(gè)想用來(lái)代替外部方法的新功能。外部方法能做到的,它都能做到,而且它能和安全性及管理系統(tǒng)更好地集成,在集成方面提供更多的靈活性,它還有很多對(duì) Zope API 中公開(kāi)的全部 Zope 功能的訪(fǎng)問(wèn)。
一個(gè)腳本基本上就是一個(gè)短小的 Python 程序。它可以定義類(lèi)或函數(shù),但不是必須的。它被作為對(duì)象安裝在 Zope 文件夾中,然后就可以把它當(dāng)作 DTML 變量或調(diào)用(就像一個(gè)外部方法)來(lái)調(diào)用或者“從 Web 中”(在 Zope 中的意思就是它將被當(dāng)作頁(yè)來(lái)調(diào)用)調(diào)用它。當(dāng)然,這意味著腳本可以像 CGI 程序那樣生成對(duì)表單提交的響應(yīng),但卻沒(méi)有 CGI 的開(kāi)銷(xiāo)。確實(shí)是一個(gè)很棒的功能。此外,腳本有權(quán)訪(fǎng)問(wèn)被調(diào)用者或調(diào)用者對(duì)象(通過(guò)“context”對(duì)象)、對(duì)象所在的文件夾(通過(guò)“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í)犯過(guò)這種錯(cuò)誤)。但事實(shí)并非如此。由于安全性限制,只有 Product 可以被導(dǎo)入,而不是什么模塊都可以。一般而言,Zope 的設(shè)計(jì)者們認(rèn)為任何腳本編制都需要訪(fǎng)問(wèn)文件系統(tǒng),既然腳本對(duì)象是由 Web 使用 Zope 管理界面來(lái)管理,所以它們不是完全可信的。所以我打算就此打住,不給您展示示例腳本了,而是來(lái)討論 Product 和基礎(chǔ)類(lèi)。
專(zhuān)注于 Product
Product 是擴(kuò)展 Zope 的強(qiáng)大工具方法。從安裝目錄的級(jí)別來(lái)看,Product 就是位于 Zope 目錄下的“l(fā)ib/python/Products”目錄中的一個(gè)目錄。在您自己的 Zope 安裝目錄中,您可以看到很多 product 示例,但本質(zhì)上,最小的 Product 只由位于該目錄的兩個(gè)文件組成:一個(gè)可任意命名的代碼文件和一個(gè) Zope 在啟動(dòng)時(shí)調(diào)用來(lái)初始化 Product 的稱(chēng)為 __init__.py 的文件。(請(qǐng)注意:Zope 只在啟動(dòng)時(shí)讀取 Product 文件,這意味著為了測(cè)試,您必須能夠停止和重新啟動(dòng) Zope 進(jìn)程)。本文只是盡量多提供一些您能通過(guò)使用 Zope Product 做到的事的提示。
要知道的是 Product 封裝了一個(gè)或多個(gè)可從 ZClass、腳本或直接從 Web 上的 URL 使用的類(lèi)。(當(dāng)然,在最后一種情況下,Product 的實(shí)例被當(dāng)作文件夾看待;那么 URL 的最后部分指定了將被調(diào)用的方法,該方法返回任意的 HTML。)您不必一定要把 Product 當(dāng)作“可添加的”對(duì)象來(lái)對(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 類(lèi),該類(lèi)提供了很多發(fā)布方法。請(qǐng)注意 Zope 采用一種奇怪的約定來(lái)確定哪些方法可以通過(guò) Web 訪(fǎng)問(wèn) ― 如果一個(gè)方法包含有一個(gè) doc 字符串,那么該方法可通過(guò) Web 訪(fǎng)問(wèn);否則,就被認(rèn)為是私有的。
無(wú)論如何,我們還是來(lái)看一個(gè)使用了 C 模塊(我們?cè)谏厦娑x了它)的非常簡(jiǎn)單的 Product。首先來(lái)看非常簡(jiǎn)單的 __init__.py;請(qǐng)注意它只做了一件事,即告訴 Zope 我們正在安裝的類(lèi)的名稱(chēng)。更復(fù)雜的初始化腳本能做 更多的事,包括聲明由服務(wù)器維護(hù)的全局變量以及設(shè)置訪(fǎng)問(wèn)權(quán)限等等。欲了解更多詳細(xì)信息,請(qǐng)參閱在線(xiàn)文檔中的 Zope 開(kāi)發(fā)者指南,也請(qǐng)研究您的 Zope 安裝目錄中現(xiàn)成的 Product。您或許已經(jīng)猜到了,我們的示例 Product 被稱(chēng)為“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è)類(lèi),使它可被 Zope 的其它部件訪(fǎng)問(wèn),而且還將該類(lèi)注冊(cè)成具有“可添加性”。 context.registerClass 調(diào)用通過(guò)首先命名我們所導(dǎo)入的類(lèi),然后指定可被用于添加實(shí)例的方法名稱(chēng)(這個(gè)方法必須顯示一個(gè)管理頁(yè)面,且該方法將自動(dòng)與 Zope 管理界面集成)的名稱(chēng)來(lái)完成這項(xiàng)工作。酷。
我們來(lái)小結(jié)一下這個(gè)短小、簡(jiǎn)單的 Product。它會(huì)把我們的 foo.bar 函數(shù)公開(kāi)給腳本和 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ì)地說(shuō)它是可能的 Product 中最小的一個(gè),但已經(jīng)很接近了。不過(guò),它確實(shí)說(shuō)明了 Product 的一些關(guān)鍵特征。首先,請(qǐng)注意“index_html”方法:它被調(diào)用來(lái)顯示一個(gè)對(duì)象實(shí)例,這是通過(guò)構(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)行交互操作。它不做很多管理工作。它沒(méi)有交互功能。所以您可以給它添加很多東西(甚至連很有用的功能它也沒(méi)有)。我希望這對(duì)您是一個(gè)很好的開(kāi)始。
以后該做什么
對(duì) Zope Product 的簡(jiǎn)單介紹已經(jīng)告訴您如何把 C 語(yǔ)言函數(shù)從 C 代碼變?yōu)?Zope 中可用的。要學(xué)會(huì)怎么寫(xiě) Product,您還得閱讀更多文檔(其中有很多仍在完善之中),坦率地說(shuō),還要研究已有的 Product,看看它們是怎么做的。Zope 模型有很強(qiáng)大的功能和很大的靈活性,它們都很值得探究。
我目前正在做集成 C 和 Zope 的大工程:集成我的工作流工具包(workflow toolkit)。在本文發(fā)表之前,我希望能看到它的雛形。它已被列在下面的參考資料中,去看看吧;到您閱讀本文時(shí),應(yīng)該已經(jīng)能夠從中找到一個(gè)擴(kuò)展示例。祝我好運(yùn)。
- c語(yǔ)言多進(jìn)程tcp服務(wù)器示例
- 基于C語(yǔ)言編寫(xiě)一個(gè)簡(jiǎn)單的Web服務(wù)器
- C語(yǔ)言Tinyhttpd服務(wù)器源碼剖析
- 利用C語(yǔ)言實(shí)現(xiàn)http服務(wù)器(Linux)
- C語(yǔ)言實(shí)現(xiàn)簡(jiǎn)單回聲服務(wù)器
- C語(yǔ)言多線(xiàn)程服務(wù)器的實(shí)現(xiàn)實(shí)例
- 如何利用C語(yǔ)言實(shí)現(xiàn)最簡(jiǎn)單的HTTP服務(wù)器詳解
- 基于C語(yǔ)言實(shí)現(xiàn)的TCP服務(wù)器的流程分析
相關(guān)文章
Python OpenCV實(shí)現(xiàn)攝像頭人臉識(shí)別功能
這篇文章主要介紹了Python OpenCV實(shí)現(xiàn)攝像頭人臉識(shí)別,使用Python 3和OpenCV進(jìn)行攝像頭人臉識(shí)別的基本步驟,本文結(jié)合實(shí)例代碼給大家介紹的非常詳細(xì),需要的朋友可以參考下2023-07-07Python實(shí)現(xiàn)讀取文件最后n行的方法
這篇文章主要介紹了Python實(shí)現(xiàn)讀取文件最后n行的方法,涉及Python針對(duì)文件的讀取、遍歷與運(yùn)算相關(guān)操作技巧,需要的朋友可以參考下2017-02-02python+matplotlib繪制3D條形圖實(shí)例代碼
這篇文章主要介紹了python+matplotlib繪制3D條形圖實(shí)例代碼,具有一定借鑒價(jià)值,需要的朋友可以參考下2018-01-01Python流程控制 while循環(huán)實(shí)現(xiàn)解析
這篇文章主要介紹了Python流程控制 while循環(huán)實(shí)現(xiàn)解析,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2019-09-09python selenium操作cookie的實(shí)現(xiàn)
這篇文章主要介紹了python selenium操作cookie的實(shí)現(xiàn),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2020-03-0315款Python編輯器的優(yōu)缺點(diǎn),別再問(wèn)我“選什么編輯器”啦
這篇文章主要介紹了15款Python編輯器的優(yōu)缺點(diǎn),別再問(wèn)我“選什么編輯器”啦,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2020-10-10Python驗(yàn)證的50個(gè)常見(jiàn)正則表達(dá)式
這篇文章主要給大家介紹了關(guān)于利用Python驗(yàn)證的50個(gè)常見(jiàn)正則表達(dá)式的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2021-03-03python3.7 openpyxl 刪除指定一列或者一行的代碼
這篇文章主要介紹了python3.7 openpyxl 刪除指定一列或者一行,文中通過(guò)代碼給大家介紹了python3 openpyxl基本操作,代碼簡(jiǎn)單易懂,需要的朋友可以參考下2019-10-10