python之调用系统命令

本文详细介绍了Python中执行CMD命令的多种方法及其应用场景,包括os.system、os.popen、subprocess.Popen等函数的区别与联系。此外,还深入探讨了Python OS模块的功能和用法,提供了大量实用代码示例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

 一、python中执行cmd

目前我使用到的python中执行cmd的方式有三种

使用os.system("cmd")

    该方法在调用完shell脚本后,返回一个16位的二进制数,低位为杀死所调用脚本的信号号码,高位为脚本的退出状态码,即脚本中“exit 1”的代码执行后,os.system函数返回值的高位数则是1,如果低位数是0的情况下,则函数的返回值是0×100,换算为10进制得到256。
    如果我们需要获得os.system的正确返回值,那使用位移运算可以还原返回值:
        >>> n = os.system(test.sh)
        >>> n >> 8
        >>> 3
    这是最简单的一种方法,特点是执行的时候程序会打出cmd在linux上执行的信息。使用前需要import os。
    os.system("ls")  仅仅在一个子终端运行系统命令, 而不能获取命令执行后的返回信息

os.Popen

    这种调用方式是通过管道的方式来实现,函数返回一个file-like的对象,里面的内容是脚本输出的内容(可简单理解为echo输出的内容)。使用os.popen调用test.sh的情况:python调用Shell脚本,有两种方法:os.system(cmd)或os.popen(cmd),前者返回值是脚本的退出状态码,后者的返回值是脚本执行过程中的输出内容。实际使用时视需求情况而选择。明显地,像调用”ls”这样的shell命令,应该使用popen的方法来获得内容
    popen(command [, mode='r' [, bufsize]]) -> pipe
    tmp = os.popen('ls *.py').readlines()

subprocess.Popen

    现在大部分人都喜欢使用Popen。Popen方法不会打印出cmd在linux上执行的信息。的确,Popen非常强大,支持多种参数和模式。使用前需要from subprocess import Popen, PIPE。但是Popen函数有一个缺陷,就是它是一个阻塞的方法。如果运行cmd时产生的内容非常多,函数非常容易阻塞住。解决办法是不使用wait()方法,但是也不能获得执行的返回值了。

    Popen原型是:
    subprocess.Popen(args, bufsize=0, executable=None, stdin=None, stdout=None, stderr=None, preexec_fn=None, close_fds=False, shell=false)

    参数bufsize:指定缓冲。我到现在还不清楚这个参数的具体含义,望各个大牛指点。

    参数executable用于指定可执行程序。一般情况下我们通过args参数来设置所要运行的程序。如果将参数shell设为 True,executable将指定程序使用的shell。在windows平台下,默认的shell由COMSPEC环境变量来指定。

    参数stdin, stdout, stderr分别表示程序的标准输入、输出、错误句柄。他们可以是PIPE,文件描述符或文件对象,也可以设置为None,表示从父进程继承。

    参数preexec_fn只在Unix平台下有效,用于指定一个可执行对象(callable object),它将在子进程运行之前被调用。

    参数Close_sfs:在windows平台下,如果close_fds被设置为True,则新创建的子进程将不会继承父进程的输入、输出、错误管 道。我们不能将close_fds设置为True同时重定向子进程的标准输入、输出与错误(stdin, stdout, stderr)。

    如果参数shell设为true,程序将通过shell来执行。

    参数cwd用于设置子进程的当前目录。

    参数env是字典类型,用于指定子进程的环境变量。如果env = None,子进程的环境变量将从父进程中继承。

    参数Universal_newlines:不同操作系统下,文本的换行符是不一样的。如:windows下用’/r/n’表示换,而Linux下用 ‘/n’。如果将此参数设置为True,Python统一把这些换行符当作’/n’来处理。

    参数startupinfo与createionflags只在windows下用效,它们将被传递给底层的CreateProcess()函数,用 于设置子进程的一些属性,如:主窗口的外观,进程的优先级等等。

    subprocess.PIPE
    在创建Popen对象时,subprocess.PIPE可以初始化stdin, stdout或stderr参数,表示与子进程通信的标准流。

    subprocess.STDOUT
    创建Popen对象时,用于初始化stderr参数,表示将错误通过标准输出流输出。

    Popen的方法:
    Popen.poll() 
    用于检查子进程是否已经结束。设置并返回returncode属性。

    Popen.wait() 
    等待子进程结束。设置并返回returncode属性。

    Popen.communicate(input=None)
    与子进程进行交互。向stdin发送数据,或从stdout和stderr中读取数据。可选参数input指定发送到子进程的参数。 Communicate()返回一个元组:(stdoutdata, stderrdata)。注意:如果希望通过进程的stdin向其发送数据,在创建Popen对象的时候,参数stdin必须被设置为PIPE。同样,如 果希望从stdout和stderr获取数据,必须将stdout和stderr设置为PIPE。

    Popen.send_signal(signal) 
    向子进程发送信号。

    Popen.terminate()
    停止(stop)子进程。在windows平台下,该方法将调用Windows API TerminateProcess()来结束子进程。

    Popen.kill()
    杀死子进程。

    Popen.stdin 
    如果在创建Popen对象是,参数stdin被设置为PIPE,Popen.stdin将返回一个文件对象用于策子进程发送指令。否则返回None。

    Popen.stdout 
    如果在创建Popen对象是,参数stdout被设置为PIPE,Popen.stdout将返回一个文件对象用于策子进程发送指令。否则返回 None。

    Popen.stderr 
    如果在创建Popen对象是,参数stdout被设置为PIPE,Popen.stdout将返回一个文件对象用于策子进程发送指令。否则返回 None。

    Popen.pid 
    获取子进程的进程ID。

    Popen.returncode 
    获取进程的返回值。如果进程还没有结束,返回None。

例子一枚

 
  1. p = Popen("cp -rf a/* b/", shell=True, stdout=PIPE, stderr=PIPE)
  2. p.wait()
  3. if p.returncode != 0:
  4. print "Error."
  5. return -1

使用commands.getstatusoutput方法

    这个方法也不会打印出cmd在linux上执行的信息。这个方法唯一的优点是,它不是一个阻塞的方法。即没有Popen函数阻塞的问题。使用前需要import commands。

比如

    status, output = commands.getstatusoutput("ls")  
    还有只获得output和status的方法:
    commands.getoutput("ls")  
    commands.getstatus("ls")

二、OS模块

 

1.os

os

模块类型c操作s说明b备注
分隔符os.sep可以取代操作系统特定的路径分割符文件夹分隔符,windows中是 \ 
 os.extsepv 扩展名分隔符,windows中是 . 
 os.pathsep 扩展名分隔符,windows中是 ;
 os.linesep字符串给出当前平台使用的行终止符。例如,Windows使用'\r\n',Linux使用'\n' 而Mac使用'\r'。换行分隔符,windows中是 \r\n 
获得基本信息os.name字符串指示你正在使用的平台。比如对于Windows,它是'nt',而对于Linux/Unix用户,它是'posix'系统名称('posix', 'nt', 'os2', 'mac', 'ce' or 'riscos')
 os.getcwd() 函数得到当前工作目录, 
 os.curdir返回当前目录('.') 
 os.getenv()和os.putenv() 函数分别用来读取和设置环境变量。 
文件夹,路径操作os.walk(path)列举path下的所有文件、文件夹 
 os.listdir(path)列出dirname下的目录和文件 
 os.makedir(path)创建文件夹创建已存在的文件夹将异常
 os.makedirs(path)递归式的创建文件夹创建已存在的文件夹将异常
 os.rmdir(path)删除一个文件夹删除非空的文件夹将异常
 os.remove() 函数用来删除一个文件。 
 os.removedirs(path)归的删除文件夹,直到有一级的文件夹非空文件夹路径不能以'\'结束
 os.chdir(dirname)改变工作目可以改路径,但是不能覆盖目标文件
 os.renames(src,dst)递归式的给文件或文件名改名 
 os.rename(src,dst)给文件或文件夹改名 
 os.chdir(dirname)改变工作目录到dirname 
时间getatime(path)文件或文件夹的最后访问时间,从新纪元到访问时的秒数 
 getmtime(path)文件或文件夹的最后修改时间 
 getctime(path)文件或文件夹的创建时间 

2.os.path

os.path

操作说明备注
os.path.isfile()和os.path.isdir()函数分别检验给出的路径是一个文件还是目录,返回bool值 
os.path.exists()函数用来检验给出的路径是否真地存在 返回bool 
os.path.getsize(name)获得文件大小,如果name是目录返回0L 返回long 单位是字节 
os.path.abspath(name)获得绝对路径 
os.path.normpath(path)规范path字符串形式, 结果一般情况下把/变为// 
os.path.split(name)将name分割成路径名和文件名,结果为(路径名,文件名.文件扩展名)(事实上,如果你完全使用目录,它也会将最后一个目录作为文件名而分离,同时它不会判断文件或目录是否存在) 
os.path.splitext(filename)分离文件名与扩展名 结果为(filename,扩展名) 如果参数为一个路径 则返回(路径,'') 
os.path.join(path,name)连接目录与文件名或目录 结果为path/name 
os.path.basename(path)返回文件名 实际为把path的最后一个"/"分割,返回后者。不管参数是一个路径还是文件 与os.path.split(name)相同 不同之处后者返回两个值得元组 
os.path.dirname(path)返回文件路径 实际为把path的最后一个"/"分割,返回前者。不管参数是一个路径还是文件 
os.system()函数用来运行shell命令 

 

3.os进程

os模块包装了不同操作系统的通用接口,使用户在不同操作系统下,可以使用相同的函数接口,返回相同结构的结果。

操作说明备注
execl(path)运行一个程序来替代当前进程,会阻塞式运行 
_exit(n)退出程序 
startfile(filename)用与文件关联的程序运行,关联程序打开后,立即返回 
system(cmd)运行一个程序或命令,会立即返回,并在cmd执行完成后,会返回cmd退出代码 
os.path在不同的操作系统中调用不同的模块,是一个可import的模块,这个模块中提供很多有用的操作 
abspath(path)回path的绝对路径,若path已经是绝对路径了,则保持。 
basename(path)返回path中的文件名 
commonprefix(list)返回list中的统一前缀,用于获得一组字符串的左起相同的内容 
dirname(path)返回path中的文件夹部分,结果不包含'\' 
exists(path)文件或文件夹是否存在 
getsize(path)文件或文件夹的大小,若是文件夹返回0 
isabs(path)返回是否是绝对路径 
isfile(path)返回是否是文件路径 
isdir(path)返回是否是文件夹路径 

islink(path)

返回是否是快捷方式

 
join(path1,path2,...)将path进行组合,若其中有绝对路径,则之前的path将被删除 
normcase(path)转换路径中的间隔符 
normpath(path)转换路径为系统可识别的路径 
realpath(path)转换路径为绝对路径 
split(path)将路径分解为(文件夹,文件名) 
splitext(path)将路径分解为(其余部分,.扩展名),若文件名中没有扩展名,扩展名部分为空字符串 

在操作与系统不支持的对象时,抛出OSError异常。

 

四、一些写的例子

# -*- coding:utf-8 -*-
'''
删除media下的文件
'''

import os

my_file_ROOT = 'C:/Users/xianmengxuanling/Desktop/star'
my_file_media = 'media'
del_Media = my_file_ROOT + '/' + my_file_media

def DeleteMedia(del_Media):
    for i in os.listdir(del_Media):
        del_dir = None
        del_dirFile = os.path.join(del_Media,i)
        if os.path.isfile(del_dirFile):
            #如果是文件则删除
            print(del_dirFile)
            os.remove(del_dirFile)
        else:
            #不是文件只能是目录,就遍历后再删除
            del_dir = del_dirFile
            for j in os.listdir(del_dir):
                del_dir_files = os.path.join(del_dir, j)
                print(del_dir_files)
                os.remove(del_dir_files)

DeleteMedia(del_Media)
print ('删除完了上传的图片和文件!')

 

# -*- coding:utf-8 -*-
'''
在每个APP的migrations文件夹下,保留__init__.py文件,删除其他文件
'''

import os
import os.path

my_file_ROOT = 'C:/Users/xianmengxuanling/Desktop/star'
my_file_APP = ['file_db','files_db','img_db','imgs_db','pro_db','xadmin']
my_file_migartions = 'migrations'
my_file_init = '__init__.py'
undel_file_list = [r'\__init__.py',]

def DeleteFiles(path,fileList):
    for parent,dirnames,filenames in os.walk(path):

        FullPathList = []
        DestPathList = []

        for x in fileList:
            DestPath = path + x
            DestPathList.append(DestPath)


        for filename in filenames:                   
            FullPath = os.path.join(parent,filename)
            FullPathList.append(FullPath)


        for xlist in FullPathList:
            if xlist not in DestPathList:
                os.remove(xlist)


def DelFiles():
    for i in my_file_APP:
        del_ROOT = my_file_ROOT + '/' + i + '/' + my_file_migartions
        DeleteFiles(del_ROOT, undel_file_list)

DelFiles()
print ('删除完了初始化的文件!')

 

# -*- coding:utf-8 -*-
'''
创建media下的几个空文件夹
'''

import os

my_file_ROOT = 'C:/Users/xianmengxuanling/Desktop/starr'
my_file_media = 'media'
add_Media = my_file_ROOT + '/' + my_file_media
my_file_media_dir = ['file','files','img','imgs','soft','pic_folder']

def mkdir(add_Media):
    for i in my_file_media_dir:
        add_dir = add_Media + '/' + i
        # print(add_dir,os.path.exists(add_dir))
        if os.path.exists(add_dir)==False:  # 判断是否存在文件夹如果不存在则创建为文件夹
            os.makedirs(add_dir)  # 创建文件时如果路径不存在会创建这个路径
            print(add_dir+'创建好了')
        else:
            print ('没有这样的文件路径: %s ' % add_dir)

mkdir(add_Media)

 

执行操作的文件结构

--star

    --file_db

        --migrations

            __init__.py

            0001_initial.py

    --files_db

        ...

    --img_db

        ...

    --imgs_db

        ...

    --media

        --file

            xcsdfsdf.jpg

            ...

        --files

            ...

        --img

            ...

        --imgs

            ...

        --soft

            ...

        --pic_folder

            ...

        sdsadas.jpg

        ...

104740_TmPQ_3018050.png

# -*- coding:utf-8 -*-
'''
打开管理员cmd面板
'''
import subprocess
# 方式1:通过runas /savecred
subprocess.Popen("runas /savecred /user:Administrator cmd", shell=True)

# 方式2:通过pexpect方式
import codecs
from pexpect import popen_spawn
child=popen_spawn.PopenSpawn(r'runas /user:Administrator cmd')
# -*- coding:utf-8 -*-
'''
以管理员方式启动浏览器
'''
import os
# os.system("runas /user:Administrator \"C:\Program Files\Internet Explorer\iexplore.exe\"")

214652_e8um_3018050.png

启动窗口

如果有对是否启用空密码本组账户的问题,请参照下面修改:

在运行框输入

 gpedit.msc

 

214956_ahBm_3018050.png

python获取文件上一级目录:取文件所在目录的上一级目录

os.path.abspath(os.path.join(os.path.dirname('settings.py'),os.path.pardir))

os.path.pardir是父目录,os.path.abspath是绝对路径

举例具体看一下输出:

    print os.path.dirname(os.path.abspath("__file__"))
    print os.path.pardir
    print os.path.join(os.path.dirname("__file__"),os.path.pardir)
    print os.path.abspath(os.path.join(os.path.dirname("__file__"),os.path.pardir))

运用示例:

os.path.dirname(os.getcwd())#当前目录的上一级路径

五、一些问题

1.系统中文乱码问题

164255_cM7U_3018050.png

问题原因是系统显示不能为utf-8

164430_fiPs_3018050.png

164539_h8QD_3018050.png

164559_I6AO_3018050.png

两项修改为gbk即可

2.如何使用system的多个命令

利用os.chdir(path)切换路径,执行多个命令

# -*-coding:utf-8-*-
# Author:WYC

import os
# os.system('date')#设置为GBK即可解决乱码问题
my_file_ROOT = 'D:/star'
operate0 = 'python manage.py migrate --fake-initial'#确保表建立的数量完整
operate1 = 'python manage.py makemigrations'
operate2 = 'python manage.py migrate'
#operate3 = 'manage.py createsuperuser'#执行有问题,还没找到解决方法

print(os.getcwd())
os.chdir(my_file_ROOT)#切换工作目录
print(os.getcwd())
os.system(operate0)
os.system(operate1)
os.system(operate2)
#以上操作在数据库建立相应的空库后,可以连续执行初始化

3.脚本创建超级管理员的问题

172729_TmJA_3018050.png

允许之后,系统本身的cmd是不能关联的,所以用了cmder

173017_P09T_3018050.png

就会跳出这个框框

173049_kVIt_3018050.png

还没解决,创建超管的操作,如有方法,请留言

 

 参考文档:

1.python笔记之调用系统命令:https://www.zybuluo.com/bergus/note/232338

2.关于python调用cmd命令:https://www.cnblogs.com/lrw3716740/p/5158494.html

3.python os 命令,及判断文件夹是否存在:https://www.cnblogs.com/wq242424/p/5803721.html

4.解决:登录失败,用户账号限制。可能的原因包括不允许空密码,登录时间限制,或强制的策略限制:https://blog.youkuaiyun.com/xuhui_liu/article/details/73832743

5. Windows 下 Python 脚本以管理员方式执行 Windows 命令或者程序:https://testerhome.com/topics/11793

转载于:https://my.oschina.net/u/3018050/blog/1799044

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值