使出Python的六脉神剑,让Python拥有无限扩展性

开发 后端
我们知道,Python的API非常多,功能非常强大,而且非常易用。Python之所以强大,一个重要原因是因为Python非常容易与其他编程语言交互。这就让Python拥有了无限扩展性。就算Python无法实现某个功能,可以用其他语言实现,然后Python直接调用即可。

[[350168]]

我们知道,Python的API非常多,功能非常强大,而且非常易用。Python之所以强大,一个重要原因是因为Python非常容易与其他编程语言交互。这就让Python拥有了无限扩展性。就算Python无法实现某个功能,可以用其他语言实现,然后Python直接调用即可。

Python与其他编程语言交互,主要有如下两种方法:

(1)调用动态库,如.dll,.so等;

(2)直接执行外部命令,并接收外部命令的返回结果;

第1种方法我会在后面的文章中详细讨论,本文主要讲解如何使用Python执行外部的命令,并传递参数和接收返回值,然后做更进一步的处理。本文将介绍6种执行外部命令的方法,并比较这6中方法的优缺点。史称这6种执行外部命令的方法为六脉神剑。

Python执行外部命令的6种方法:

1. system函数

基本的调用格式如下:

  1. import os 
  2. os.system("some_command with args"); 

system函数会将命令和参数传递给系统的Shell。这么做非常好,因为您实际上可以用这种方式一次运行多个命令,并设置管道和输入/输出重定向。例如:

  1. import os 
  2. os.system("cat command.py | grep -n subprocess > result.txt"

执行这段代码,会在当前目录生成一个result.txt文件。

尽管这样做很方便,但必须手动处理转义字符(例如空格等)。所以这样做只是让你简单地运行Shell程序,而不是扩展程序的功能。

2. popen函数

基本调用格式如下:

  1. import os 
  2. stream = os.popen("some_command with args"

popen函数与os.system函数的功能相同,只是popen函数提供了一个用于操作文件的对象,可用使用标准输入输出的方式来访问文件中的数据。popen函数还有其他3种变体,它们对I/O的处理略有不同。如果将所有内容都作为字符串传递,那么命令将传递到Shell程序;如果将它们作为列表传递,则无需担心转义任何内容。例如:

  1. import os 
  2. stream = os.popen("cat command.py | grep -n subprocess"
  3. print(type(stream)) 
  4. result = stream.readlines() 
  5. print(type(result)) 
  6. print(result) 

执行这段代码,会输出如下内容:

  1. <class 'os._wrap_close'
  2. <class 'list'
  3. ['1:import subprocess\n''2:subprocess.run(["ls", "-l"])\n''5:subprocess.call(["ls", "-l"])\n''8:os.system("cat command.py | grep -n subprocess > result.txt")\n'

我们可以看到,readlines方法以列表形式返回命令的执行结果。

3. Popen类

subprocess模块的Popen类。该类可用于替换os.popen函数。但Popen类的缺点是由于功能过于强大,所以使用起来稍微复杂一些。例如:

  1. print(subprocess.Popen("echo Hello World", shell=True, stdout=subprocess.PIPE).stdout.read()) 

这行代码可以用来替换下面的代码:

  1. print(os.popen("echo Hello World").read()) 

关于Popen类的一个更复杂的例子如下:

  1. import subprocess 
  2. p = subprocess.Popen('ls', shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) 
  3. for line in p.stdout.readlines(): 
  4.     print(line.decode("utf-8").strip()) 
  5. retval = p.wait() 

这段代码通过标准输出的readlines方法读取了ls命令返回结果的所有行,并将这些内容输出到Console。最后用wait方法等待ls命令执行完,最后结束程序。

Popen类相对于popen函数的优势是将所有的选项都统一放在了Popen类中,而不是需要4个不同的popen函数完成这些工作。

4.call函数

来自subprocess模块的call函数。与Popen类一样,拥有相同的参数,但call函数只会等待命令执行完并提供返回代码才结束。例如:

  1. return_code = subprocess.call("echo Hello World", shell=True
  2. print(return_code) 

5. run函数

如果读者使用的是Python 3.5或更高版本,则可以使用新的subprocess.run函数,该函数与上面的代码非常相似,但是更加灵活,并在命令完成执行后返回CompletedProcess对象。例如:

  1. import subprocess 
  2. result = subprocess.run(["ls""-l"]) 
  3. print(type(result)) 

6. 类C函数

os模块还提供了与C语言类似的fork / exec / spawn函数,但是我不建议直接使用它们,例如:

  1. import os 
  2. print(os.execl('/bin/ls'' ')) 

最后,请注意,对于这些执行外部命令的方法,需要将这些命令执行后参数的字符串传递回程序,有时需要对这些传回的字符串进行转移。如果你无法完全信任这些字符串,那么有可能会带来严重的安全隐患。例如,如果用户正在输入字符串的某些/任何部分。如果不确定,请仅将这些方法与常量一起使用。为了更好地说明这一点,请看下面的代码。

  1. print(subprocess.Popen("echo %s " % user_input, stdout=PIPE).stdout.read()) 

我们可以想象,当用户输入了“I love your harddisk && rm -rf /”,这将删除硬盘中的所有数据。所以如果你对用户的输入无法完全信任的话,请将变量user_input改成常量,不让用户任意输入。

本文转载自微信公众号「极客起源」,可以通过以下二维码关注。转载本文请联系极客起源公众号。

 

责任编辑:武晓燕 来源: 极客起源
相关推荐

2010-09-17 10:57:28

诺基亚

2017-07-07 09:47:05

CTO代码技术

2014-11-18 09:11:54

2009-09-23 10:43:22

2017-03-08 16:34:18

2011-05-04 16:23:07

2009-08-26 10:41:21

防止数据丢失

2021-09-02 09:42:11

测试软件可扩展性开发

2010-06-30 17:15:39

向外扩展SQL Ser

2022-04-07 14:42:25

计算原理计算机科学鸿蒙

2010-07-21 11:21:05

SQL Server

2022-09-05 15:17:34

区块链比特币可扩展性

2010-07-01 11:38:13

向外扩展 SQL Se

2018-04-10 14:38:10

区块链

2015-05-13 17:15:01

Elasticsear分布式搜索插件

2009-09-03 17:18:40

C#扩展性对象模型

2009-09-03 17:33:08

C#常规扩展性模型

2009-03-11 11:52:08

开放平台

2017-04-12 11:02:50

Apache Meso资源利用容器

2021-12-03 14:41:00

云存储可扩展性存储
点赞
收藏

51CTO技术栈公众号