当前位置: 首页 > 科技观察

使用Python的六脉魔剑,让Python拥有无限的可扩展性

时间:2023-03-13 05:45:56 科技观察

我们知道Python的API非常多,功能非常强大,而且非常好用。Python强大的一个重要原因是因为Python非常容易与其他编程语言进行交互。这使得Python具有无限的可扩展性。即使Python不能实现某个功能,也可以用其他语言实现,然后Python可以直接调用。Python与其他编程语言交互主要有两种方式:(1)调用动态库,如.dll、.so等;(2)直接执行外部命令并接收外部命令的返回结果;第一种方法我会在后面的文章中详细讨论。本文主要讲解如何使用Python执行外部命令,传递参数和接收返回值,然后做进一步的处理。本文将介绍6种执行外部命令的方法,并比较这6种方法的优缺点。这6种执行外部命令的方法在历史上被称为六脉神剑。Python执行外部命令的方式有6种:1、系统函数的基本调用格式如下:importosos.system("some_commandwithargs");系统函数会将命令和参数传递给系统Shell。这很棒,因为您实际上可以通过这种方式一次运行多个命令,并设置管道和输入/输出重定向。例如:importosos.system("catcommand.py|grep-nsubprocess>result.txt")执行这段代码,会在当前目录下生成一个result.txt文件。虽然这很方便,但必须手动处理转义字符(如空格等)。所以这样做只是让你可以简单地运行Shell程序,而不是扩展程序的功能。2、popen函数的基本调用格式如下:importosstream=os.popen("some_commandwithargs")popen函数的作用与os.system函数相同,只是popen函数提供了一个对象用于操作文件,可以使用标准输入输出的方式访问文件中的数据。popen函数还有其他3个变体,它们处理I/O的方式略有不同。如果将所有内容都作为字符串传递,则命令将传递给shell;如果将它们作为列表传递,则无需担心转义任何内容。例如:importosstream=os.popen("catcommand.py|grep-nsubprocess")print(type(stream))result=stream.readlines()print(type(result))print(result)执行这段代码,它会输出以下内容:['1:importsubprocess\n','2:subprocess.run(["ls","-l"])\n','5:subprocess.call(["ls","-l"])\n','8:os.system("catcommand.py|grep-nsubprocess>result.txt")\n']我们可以看到,readlines方法以列表的形式返回命令的执行结果。3.Popen类subprocess模块??的Popen类。此类可用于替换os.popen函数。但是Popen类的缺点是使用起来有点复杂,因为它太强大了。例如:print(subprocess.Popen("echoHelloWorld",shell=True,stdout=subprocess.PIPE).stdout.read())这行代码可以用来替换下面的代码:print(os.popen("echoHelloWorld").read())Popen类的一个更复杂的例子如下:.readlines():print(line.decode("utf-8").strip())retval=p.wait()这段代码通过标准输出的readlines方法读取ls命令返回的所有行,并将内容输出到控制台。最后使用wait方法等待ls命令执行完毕,最后结束程序。Popen类相对于popen函数的优势在于所有选项都统一在Popen类中,而不是需要4个不同的popen函数来完成这些任务。4、call函数来自subprocess模块??的call函数。与Popen类一样,它具有相同的参数,但调用函数只会等待命令执行并在结束前提供返回码。例如:return_code=subprocess.call("echoHelloWorld",shell=True)print(return_code)5.run函数如果读者使用的是Python3.5或更高版本,可以使用新的subprocess.run函数,它与上面的代码很相似,但是更加灵活,在命令执行完毕后返回一个CompletedProcess对象。例如:importsubprocessresult=subprocess.run(["ls","-l"])print(type(result))6.类C函数os模块也提供了类似于C语言的fork/exec/spawn函数,但是I不建议直接使用,例如:importosprint(os.execl('/bin/ls',''))最后请注意,对于这些执行外部命令的方法,这些后面的参数字符串执行的命令需要传回程序有时需要传输这些返回的字符串。如果您不能完全信任这些字符串,则可能存在严重的安全风险。例如,如果用户正在键入字符串的某些/任何部分。如有疑问,请仅将这些方法与常量一起使用。为了更好地说明这一点,请看下面的代码。print(subprocess.Popen("echo%s"%user_input,stdout=PIPE).stdout.read())我们可以想象,当用户输入“Iloveyourharddisk&&rm-rf/”时,这会删除硬盘磁盘的所有数据。所以如果不能完全信任用户的输入,请将变量user_input改为常量,防止用户随意输入。本文转载自微信公众号“极客起源”,可通过以下二维码关注。转载本文请联系极客本源公众号。