python3调用linux/shell—【标准库:os模块&subprocess模块】

一、python 调用shell知识体系

python一门胶水语言,能够调用各种语言缩写的程序,当前wiki主要使用调用shell/linux命令:
在这里插入图片描述

几个关键注意点:

  1. 输入

字符串形式:cmd通过字符串格式输入,os、subprocess皆支持;特别注意参数传入,按照python的字符串要求传入即可(%s,str.format(),python3 f表达式)。
命令以列表形式传入:当前只有subprocess模块支持

  1. 执行linux结果

打印执行结果 :os模块默认打印;subprocess.Popen()实例不指定stdout,stderr时候。
返回执行结果状态 :os.system();subprocess.run(cmd).returncode,subprocess.call(cmd),subprocess.check_call(cmd),subprocess.getstatusoutput()[0]
返回执行结果,可以将结果赋值给变量 :os.popen().raeds();subprocess.Popen(cmd,stdout=subprocess.PIPE, stderr=subprocess.PIPE).run(),subprocess.check_output(),subprocess.getoutput(),subprocess.getstatusoutput()[1]
将执行结果打印到文件中:两种思路,一种是通过linux本身自带的重定向写入文件,另一种是使用subprocess指定stdout为本地文件即可

  1. 两个模块的对比:

返回结果:
os.system(cmd),打印结果,返回执行结果状态(0执行成功);
os.popen(cmd),打印结果,同时返回执行结果(一个打开的文件对象);
subprocess模块可以根据实际需求返回对应的结果。
使用场景:
os模块,常常用于简单的linux命令操作
subprocess模块,长用于shell等大型交付场景使用(个人建议直接使用该模块)

个人建议,无论简单,还是复杂的linux操作,直接使用subprocess模块

二、使用步骤

python源码示例:

# -*- coding:utf-8 -*-
import os, subprocess, time

#该文件测试python嗲用shell的四种方法

current_workspace = os.path.join(os.path.dirname(os.path.abspath(__file__)))
workspace='/mnt/e/00.WORKSPACE/00.Python_Develop/ToolsLibrarByPython'

'''
os.system() 调用的C库
def system(command: StrOrBytesPath) -> int: ... 返回整数,返回0则表示执行成功
# os.system(str) 方法:
#  1.可以执行linux命令,可以加参数
#  2.可以执行shell脚本,也可以加参数
#  3.特别的,重定向可以直接通过linux重定向进行,
#    但是这样重定向输出局限于当前linux执行的服务器,无法重定向到当前程序执行的目录
'''
def excute_shell_by_os_system():
    # cmd -> str
    status = os.system('ls')
    print(status)

    #cmd命令,+参数(python str 语法加参数)
    status = os.system('find %s -name "*.py"|sort' %workspace) #python str 占位符号
    print(status)

    status = os.system('find {} -type f'.format(workspace)) #python str.format()
    print(status)

    status = os.system(f"find {workspace} -type f") #python str f表达式
    print(status)

    #cmd 执行shell脚本
    status = os.system('./shell_demo.sh')
    print(status)
    
    #cmd 执行带有参数的shell脚本
    status = os.system('./shell_demo_with_param.sh %s' %workspace)
    print(status)
   
    #cmd 执行shell脚本, 重定向到某个文件
    status = os.system('./shell_demo.sh > %s' %(os.path.join(current_workspace, 'log.txt')))
    print(status) 

    #cmd 执行shell脚本, 终端输出同时写入
    status = os.system('./shell_demo.sh|tee %s' %(os.path.join(current_workspace, 'log1.txt')))
    print(status)
  
'''
os.popen(cmd) 
return <class 'os._wrap_close'>:返回值是连接管道的文件对象
该方法返回linux命令执行的结果
read()方法返回,linux执行命令输出;
readline()方法返回第一行;
readlines()方法返回:
['total 28\n', '-rwxrwxrwx 1 root root 9000 Oct 19 23:04 log.txt\n',]
'''
def excute_shell_by_os_popen():
    return_content = os.popen('ls -l')
    #print(type(return_content.read())) #<class 'str'> 注意:每次读取之后,就会释放,第二次就读取不到
    print(return_content.read())

    return_content = os.popen('ls -l')
    print(return_content.readline())
    print('-------------------------------------')

    return_content = os.popen('ls -l')
    print(return_content.readlines())

    return_content = os.popen('./shell_demo.sh')
    print(return_content.readline())

    return_content = os.popen('./shell_demo.sh', 'r')
    print(type(return_content))

    return_content = os.popen('find {} -type f'.format(workspace))
    print(return_content.readline())

'''
python 3已经用subprocess代替commands模块
Deprecated since version 2.6: The commands module has been removed in Python 3. 
Use the subprocess module instead.'''
def excute_shell_by_commands():
    pass

'''
return <class 'subprocess.CompletedProcess'>
'''
def excute_shell_by_subprocess():
    result = subprocess.run('ls -l', shell=True)#默认打印linux执行结果
    print("-------------------------------------")
    print(result) #CompletedProcess(args='ls -l', returncode=0)
    print(result.args) #ls -l
    print(result.returncode) #0 表示执行成功
    print(result.stdout) #默认传入None
    print(result.stderr)#默认传入None

    '''
    文件重定向
    '''
    #使用linux自带的重定向输出将打印结果保存到文件中
    result = subprocess.run('ls -l > %s'%(os.path.join(current_workspace, 'stdout_o.log')), shell=True)#保存到文件
    result = subprocess.run('ls -l |tee %s'%(os.path.join(current_workspace, 'stdout_o.log')), shell=True)#打印并保存到文件
    if result.returncode != 0:
        print("excute '%s' failed!" % result.args)
    else:
        print("excute '%s' successful!!" % result.args)   

    #将终端打印的信息保存到文件中【输出内容和错误信息分别保存到对应的文件】
    #stderr file对象
    #stdout file对象
    with open(os.path.join(current_workspace, 'stdout.log'), 'w') as f_o:
        with open(os.path.join(current_workspace, 'stderr.log'), 'w') as f_e:
            result = subprocess.run('ls -l', shell=True, stderr=f_e, stdout=f_o)
            if result.returncode != 0:
                print("excute '%s' failed!" % result.args)
            else:
                print("excute '%s' successful!!" % result.args)
    
    print("--------------------------------------*****---------------------------------------------")
    result1 = subprocess.run(['find', workspace,'-type','f'], shell=False) #特别注意这个位置 shell设置为False,否则不生效
    print(result1)

    result = subprocess.run('ls -l', shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)# 返回变量
    print(result)#return tuple(stdout, stderr)///tuple(bytes, bytes)

def excute_shell_by_subprocess_Popen():
    #Popen
    print("--------------------------------------**&&**---------------------------------------------")
    # 实例化Popen对象,打印执行结果,但是进程未结束,一直处于等待中...
    # result = subprocess.Popen(['ls', '-l'])# 若没指定stdout和stderr,会打印结果, communicate会返回None
    result = subprocess.Popen(['ls', '-l'], shell=False, stdout=subprocess.PIPE, stderr=subprocess.PIPE)# return <class 'subprocess.Popen'>
    #简单说communicate() 和wait()的区别,使用 subprocess 模块的 Popen 调用外部程序,
    #如果 stdout 或 stderr 参数是 pipe,并且程序输出超过操作系统的 pipe size时,
    #如果使用 Popen.wait() 方式等待程序结束获取返回值,会导致死锁,程序卡在 wait() 调用上

    #那死锁问题如何避免呢?官方文档里推荐使用 Popen.communicate()。这个方法会把输出放在内存,
    #而不是管道里,所以这时候上限就和内存大小有关了,一般不会有问题。而且如果要获得程序返回值,
    #可以在调用 Popen.communicate() 之后取 Popen.returncode 的值。

    # Attributes:【stdin, stdout, stderr, pid, returncode】
    print("-------------------------------@@@@@@@@-----------------------------------------------")
    print(result.stdin)
    print(result.stdout.read()) #<_io.BufferedReader name=3>
    print(result.stderr.read()) #return error
    print(result.pid) # return pid:224
    print(result.returncode) # return int
    print("-------------------------------@@@@@@@@-----------------------------------------------")

    #function:【communicate(), wait(), terminate(), poll()】
    result_communicate = result.communicate()# return <class 'tuple'>
    print(result_communicate)# return (bytes, bytes)

    ## 设置等待时间,终止进程
    time.sleep(5) #设置一个等待时间,确保结果被打印
    result.terminate() #终止进程

    #该方法可以代替如上语句
    result_wait = result.wait(time.sleep(2)) #等待 time.sleep(10)进程结束,在结束当前linux进程
    print(result_wait) # return int

    print(result.poll()) #return int; 检查当前进程是够结束,若结束则返回 0
    # """Check if child process has terminated. Set and return returncode attribute."""

#subprocess another api
def excute_shell_by_subprocess_old_api():
    result = subprocess.call(['ls', '-l']) #return <class 'int'>, 0 success; 同时打印结果
    print(result)# return 0
    
    print("-------------------------------------------------------------------------------------")
    result = subprocess.check_call(['ls', '-l'])#return <class 'int'>, 0 success; 同时打印结果, same call()
    print(result)

    print("-------------------------------------------------------------------------------------")
    result = subprocess.check_output(['ls', '-l'])#return <class 'bytes'>; 返回查询结果bytes
    print(result)

    print("-------------------------------------------------------------------------------------")
    result = subprocess.getoutput(['ls', '-l'])#return <class 'str'>; 返回查询结果 str
    ##特别注意:当前返回结果,不包含 total:36(linux中显示当前所有文件的大小总和)
    print(result)

    print("-------------------------------------------------------------------------------------")
    result = subprocess.getstatusoutput(['ls', '-l'])#return <class 'tuple'>/(status, output) tuple
    print(result)#status:int ; output: str

if __name__ == '__main__':
    # demo 
    excute_shell_by_os_system()
    excute_shell_by_os_popen()
    excute_shell_by_subprocess()
    excute_shell_by_subprocess_old_api()
    excute_shell_by_subprocess_Popen()
    

总结

提示:这里对文章进行总结:
例如:以上就是今天要讲的内容,本文仅仅简单介绍了pandas的使用,而pandas提供了大量能使我们快速便捷地处理数据的函数和方法。

  • 0
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值