shell相关模块 subprocess模块

Valentina ·
更新时间:2024-11-10
· 939 次阅读

系统管理模块

shutil模块

复制和移动 1.shutil.copyfileobj(fsrc,fdst[length]) 将类似文件的对象fsrc的内容复制到类似文件的对象fdst 2.shutil.copyfile(src,dst, *, follow_symlinks=True) 将名为src的文件的内容(无元数据)复制到名为dst的文件,然后返回dst # 练习 import shutil f1 = open('/etc/hosts', 'rb') f2 = open('/tmp/zhuji', 'wb') dir(shutil) shutil.copyfileobj(f1, f2) f1.close() f2.close() 1.shutil.copy(src, dst, *, follow symlinks=True)将文件src复制到文件或目录dst。src和dst应为字符串。如果dst指定目录,则文件将使用src的基本文件名复制到dst中。返回新创建的文件的路径。 # 练习 import shutil shutil.cpoy('/etc/hosts', '/tmp/') # 常用 2.shutil.copy2(src, dst, *, follow_ symlinks=True)与copy(相同,但copy20也尝试保留所有文件元数据。 3.shutil.move(src, dst, copy function=copy2)递归地将文件或目录( src )移动到另一个位置(dst),并返回目标。 # 练习 import shutil shutil.move('/tmp/hosts', '/tmp/alist.txt') # mv 目录操作 1.shutil.copytree(src, dst, symlinks=False, ignore=None, copy. function=copy2, ignore dangling_ symlinks=False) 递归地复制以src为根的整个目录树,返回目标目录。由dst命名的目标目录不能已经存在。 # 练习 import shutil shutil.copytree('/etc/hosts','/tmp/anquan') # cp -r 2.shutil.rmtree(path, ignore errors= False, onerror=None) 删除整个目录树;路径必须指向目录(而不是指向目录的符号链接)。 # 练习 import shutil shutil.rmtree('tmp/alist.txt') # rm -rf 权限管理 1.shutil.copyhmode(src,dst,*,follow_symlinks=True) 将权限位从src复制到dst。文件内容,所有者和组不受影响。src和dst是以字符串形式给出的路径名称。 2.shutil.copystat(src,dst,*,follow_ symlinks=True) 将权限位,最后访问时间,上次修改时间和标志从src复制到dst。 3.shutil.chown(path, user = None, group=None) 更改给定路径的所有者用户和/或组

subprocess模块

概述 1.subprocess模块主要用于执行系统命令 2.subprocess模块允许你产生新的进程,连接 到它们的输入/输出/错误管道,并获得它们的 返回代码 3.本模块旨在替换几个较早的模块和功能,如os.system、os.spawn* run方法 1.subprocess.run方法在python3.5引入。早 期版本可以使用subprocess.call方法 2.直接执行命令 >>> subprocess.run('ls') >>> subprocess.run(['ls', '/home']) >>> subprocess.run('ls /home') ... ... FileNotFoundError: [Errno 2] No such file or directory: 'ls /home': 'ls /home' >>> subprocess.run(['ls', '~']) ls: cannot access ~: No such file or directory 1.通过shell执行命令 >>> subprocess.run(['ls', '~'], shell=True) >>> subprocess.run('ls /home', shell=True) 2.run方法返回值 >>> result = subprocess.run(['ls', '/home']) >>> result.args ['ls', '/home'] >>> result.returncode 0 # 练习 >>> import subprocess >>> subprocess.run('ls') # ls >>> subprocess.run(['ls', '/home']) # 没有shell环境 >>> subprocess.run('ls /home') # FileNotFoundError # 在shell环境中运行ls /home >>> subprocess.run('ls /home', shell=True)

没有shell环境,就没有环境变量、命令扩展

>>> rc = subprocess.run(['ls', '~']) ls: 无法访问~: 没有那个文件或目录 CompletedProcess(args=['ls', '~'], returncode=2) >>> rc.returncode # 相当于是$? 2 >>> rc = subprocess.run('ls ~', shell=True) >>> rc.returncode 输出和错误 1.run方法执行的结果默认打印在屏幕上,也可 以通过管道将其存储在标准输出和标准错误中 >>> result = subprocess.run(['ls', '/home'],stdout=subprocess.PIPE,stderr=subprocess.PIPE) >>> result.stdout b'alice\nbob\njerry\nlisi\nStudent\ntom\nwangwu\n' >>> print(result.stdout.decode()) alice bob jerry 2.可以通过subprocess.PIPE将命令的错误和输出保存到stderr和stdout中。这两个参数是bytes类型 >>> rc = subprocess.run('id root; id wangwu', shell=True, stderr=subprocess.PIPE, stdout=subprocess.PIPE) >>> rc.args # 执行的指令 'id root; id wangwu' >>> rc.stderr b'id: wangwu: no such user\n' >>> rc.stdout b'uid=0(root) gid=0(root) \xe7\xbb\x84=0(root)\n' >>> rc.stdout.decode() 'uid=0(root) gid=0(root) 组=0(root)\n' 字符串分为bytes类型和str类型 >>> s1 = 'we' >>> type(s1) >>> b1 = s1.encode() # 编码成bytes类型,使用utf8编码 >>> b1 b'\xe8\xbe\xbe\xe5\x86\x85' >>> type(b1) >>> b1.decode() # 解码成str类型 'we' 语法风格及布局

语法风格

变量赋值 1.python支持链式多重赋值 x = y = 10 2.另一种将多个变量同时赋值的方法称为多元赋值,采用这种方式赋值时,等号两边的对象都是元组 a,b=10,20 # 练习 >>> x = y = 10 >>> a, b = 10, 20 >>> a 10 >>> b 20 >>> c, d = (10, 20) >>> c 10 >>> d 20 >>> e, f = [10, 20] >>> e 10 >>> f 20 >>> a, b = b, a # 将a、b的值互换 合法标识符 1.python标识符字符串规则和其他大部分用C编写的高级语言相似 2.第一个字符必须是字母或下划线( _ ) 3.剩下的字符可以是字母和数字或下划线 4.大小写敏感 关键字 1.和其他的高级语言一样, python也拥有一些被称作关键这字的保留字符 2.任何语言的关键字应该保持相对的稳定, 但是因为python是一门不断成长和进化的语言,其关键字偶尔会更新 3.关键字列表和iskeyword()函数都放入了keyword模块以便查阅 # 练习 >>> import keyword >>> keyword.kwlist ['False', 'None', 'True', 'and', 'as', 'assert', 'break', 'class', 'continue', 'def', 'del', 'elif', 'else', 'except', 'finally', 'for', 'from', 'global', 'if', 'import', 'in', 'is', 'lambda', 'nonlocal', 'not', 'or', 'pass', 'raise', 'return', 'try', 'while', 'with', 'yield'] 内建 内置函数 1.除了关键字之外, python还有可以在任何一级代码使用的"内建"的名字集合, 这些名字可以由解释器设置或使用 2.虽然built-in不是关键字,但是应该把它当作"系统保留字” 3.保留的常量如: True、False、 None 4.内建不是关键字,能够被覆盖,但是不推荐这么做 [内置函数](https://docs.python.org/zh-cn/3/library/functions.html) # 练习 >>> len('abcd') 4 >>> len = 10 >>> len 10 >>> len('abcd') # 现在len是10 Traceback (most recent call last): File "", line 1, in TypeError: 'int' object is not callable >>> 10('abcd') # 数字是不能被调用的 Traceback (most recent call last): File "", line 1, in TypeError: 'int' object is not callable 模块结构及布局 编写程序时,应该建立一种统一且容易阅读的结构,并将它应用到每一个文件中去 #!/usr/bin/python3 '文档字符串,用于在帮助中显示' # 模块导入部分 import random import time # 全局变量定义 all_chs = '0123456789qwertyuiopasdfghjklzxcvbnm' # 类的定义 class MyClass: pass # 函数定义 def func(): pass # 程序主体代码 if __name__ == '__main__': mc = MyClass() func()

编程思路

以创建文件为例

1.发呆。思考程序的运行方式:交互式?非交互式?

2.思考程序有哪些功能,把这些功能编写成功能函数

3.编写程序主体代码,依次调用相关函数

4.编写函数的具体代码

import os def gen_fname(): while True: fname = input('文件名:') if not os.path.exists(fname): break print('文件已存在,请重试') return fname def gen_content(): content = [] print('请输入内容,输入END结束') while True: line = input('> ') if line == 'END': break content.append(line) return content def wfile(fname, content): with open(fname, 'w') as fobj: fobj.writelines(content) if __name__ == '__main__': fname = gen_fname() content = gen_content() content = [line + '\n' for line in content] wfile(fname, content) 文件名: /etc/hosts 文件已存在,请重试 文件名: /tmp/mytest.txt 请输入内容,输入END结束 > Hello World! > 2nd line. > 3rd line. > END ]# cat /tmp/mytest.txt Hello World! 2nd line. 3rd line. 字符串详解

序列

序列类型操作符
序列操作符 作用
seq[ind] 获得下标为ind的元素
seq[ind1:ind2] 获得下标从ind1到ind2间的元素集合
seq * expr 序列重复expr次
seq1 + seq2 连接序列seq1和seq2
obj in seq 判断obj元素是否包含在seq中
obj not in seq 判断obj元素是否不包含在seq中
# 练习 >>> '*' * 30 '******************************' >>> 'a' + '10' 'a10' >>> alist = [10,20,30,40] >>> 10 in alist True >>> 15 in alist False >>> 15 not in alist True 内建函数
函数 含义
lit(iter) 把可迭代对象转换为列表
str(obj) 把obj对象转换成字符串
tuple(iter) 把一个可迭代对象转换成一个元组对象
>>> list('hello') ['h','e','l,'l','o'] >>> list(('hello', 'world')) ['hello', 'world'] >>> str(['hello', 'world']) "['hello', 'world']" # 练习 >>> str(10) '10' >>> list('abcd') ['a', 'b', 'c', 'd'] >>> tuple('abcd') ('a', 'b', 'c', 'd') >>> alist = [10, 20, 30, 40] >>> tuple(alist) (10, 20, 30, 40) 1.len(seq):返回seq的长度 # 练习 alist = ['tmp','jee','aliqq'] for i in range(len(alist)): print('%s:%s' % (i,alist[i])) 2.enumerate:接受一个可迭代对象作为参数,返回一 个enumerate对象 # 练习 1 >>> alist = ['tom', 'jerry', 'bob', 'alice'] >>> enumerate(alist) >>> list(enumerate(alist)) [(0, 'tom'), (1, 'jerry'), (2, 'bob'), (3, 'alice')] # 练习 2 alist = ['tmp','jee','aliqq'] for item in enumerate(alist): print('%s: %s' % item) # 练习 3 for ind, name in enumerate(alist): print('%s: %s' % (ind, name)) 3.reversed(seq):接受一个序列作为参数,返回一个以 逆序访问的迭代器 # 练习 >>> import random >>> alist = [random.randint(1, 100) for i in range(10)] >>> alist [1, 66, 61, 91, 37, 71, 92, 85, 31, 95] >>> reversed(alist) >>> list(reversed(alist)) [95, 31, 85, 92, 71, 37, 91, 61, 66, 1] >>> for i in reversed(alist): ... print(i) 4.sorted(iter):接受一个可迭代对象作为参数,返回 一个有序的列表 # 练习 >>> sorted(alist) [1, 31, 37, 61, 66, 71, 85, 91, 92, 95] >>> sorted(alist, reverse=True) [95, 92, 91, 85, 71, 66, 61, 37, 31, 1]

字符串

字符串操作符 1.比较操作符:字符串大小按ASCII码值大小进行比较 >>> ord('a') 97 >>> ord('A') 65 >>> ord('中') 20013 2.切片操作符:[]、[:]、[::] 3.成员关系操作符: in、not in >>> py_str = 'Hello World!' >>> py_str[::2] 'HloWrd' >>> py_str[:-1] '!dIroW olleH'

检查标识符

1.程序接受用户输入 2.判断用户输入的标识符是否合法 3.用户输入的标识符不能使用关键字 4.有不合法字符,需要指明第几个字符不合法 格式化操作符 字符串可以使用格式化符号来表示特定含义
格式化字符 转换方式
%c 转换成字符
%s 优先用str()函数进行字符串转换
%d / %i 转成有符号十进制数
%o 转成无符号八进制数
%e / %E 转成科学计数法
%f / %F 转成浮点数
# 练习 >>> '%s is %s years old' % ('bob', 22) 'bob is 22 years old' >>> 'I am %s' % 'tom' # 只有一个%s,%后面的数据不用写到元组 'I am tom' >>> '%s is %d years old' % ('bob', 22) # 整数可以用%d 'bob is 22 years old' >>> '%d is %d years old' % ('bob', 22) # 字符串不能用%d Traceback (most recent call last): File "", line 1, in TypeError: %d format: a number is required, not str >>> '%10s%8s' % ('name', 'age') # name占10列,age占8列 ' name age' >>> '%10s%8s' % ('tom', 22) ' tom 22' >>> '%-10s%-8s' % ('name', 'age') # 负数表示左对齐 'name age ' >>> '%-10s%-8s' % ('tom', 22) 'tom 22 ' 字符串可以使用格式化符号来表示特定含义
辅助指令 作用
* 定义宽度或者小数点精度
- 左对齐
+ 在正数前面显示加号
在正数前面显示空格
# 在八进制数前面显示零0 ,在十六进制前面显示’0x或者’0X’
0 显示的数字前面填充0而不是默认的空格
>>> '97: %c' % 97 '97: a' >>> '11: %#o' % 11 '11: 0o13' >>> '11: %#x' % 11 '11: 0xb' >>> '5 / 3 = %f' % (5 / 3) '5 / 3 = 1.666667' >>> '5 / 3 = %.2f' % (5 / 3) '5 / 3 = 1.67' >>> '%10d' % 5 ' 5' >>> '%010d' % 5 '0000000005' format函数 1.使用位置参数 'my name is {} ,age {}'.format('hoho',18) 2.使用关键字参数 'my name is {name},age is {age}'.format({'name':'bob', 'age':23}) 3.填充与格式化 {:[填充字符][对齐方式 ][宽度]} 4.使用索引 'name is {0[0]} age is {0[1]}'.format(['bob', 23]) # 练习 >>> '{} is {} years old'.format('bob', 22) 'bob is 22 years old' >>> '{} is {} years old'.format(22, 'bob') '22 is bob years old' >>> '{1} is {0} years old'.format(22, 'bob') 'bob is 22 years old' # 第0个位置的数据是列表,根据第0个位置的下标取值 >>> '{0[0]} is {0[1]} years old'.format(['bob', 22]) 'bob is 22 years old'

创建用户

1.编写一个程序,实现创建用户的功能 2.提示用户输入用户名 3.随机生成8位密码 4.创建用户并设置密码 5.将用户相关信息写入指定文件 # 练习 import sys import string import random all_chs = string.ascii_letters + string.digits def gen_pass(n=8): result = [random.chice(all_chs) for i in range(n)] return ''.join(result) def adduser(user, password, fnme): info = '''用户信息: 用户名: %s 密码: %s ''' % (user, password) rc = subprocess.run( 'id %s' % user, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE ) if rc.returncode == 0: print('%s已存在' % run) exit(1) # 结束程序,$? => 1 subprocess.run( # 创建用户 'useradd %s' % user, shell=True ) subprocess.run( # 添加密码 'echo %s | passwd --stdin %s' % (password, user), shell=True ) with open(fname,'a') as fobj: # 将用户名和密码写入文件 fobj.write(info) if __name__ == '__main__': pwd = gen_pass() username = sys.argv[1] fname = 'users.txt' adduser(username, pwd, fname) 全局变量

在函数外面定义的变量,从它定义的开始位置,一直到程序结束,都可见可用。

一般来说,变量的值自始至终都不需要变化,可以设置为全局变量。

局部变量

在函数内部定义的变量,只能在本函数内部使用。

生成随机字符串

>>> import string >>> import random >>> all_chs = string.ascii_letters + string.digits >>> result = [random.choice(all_chs) for i in range(8)] >>> result ['V', '1', '1', 'R', '1', '7', 'm', '4'] >>> ''.join(result) 'V11R17m4' >>> '-'.join(result) 'V-1-1-R-1-7-m-4' >>> '##'.join(result) 'V##1##1##R##1##7##m##4' 原始字符串操作符 1.原始字符串操作符是为了对付那些在字符串中出现的特殊字符 2.在原始字符串里,所有的字符都是直接按照字面的意思来使用,没有转义特殊或不能打印的字符 >>> winPath = "c:\windows\temp" >>> print(winPath) c: windows emp >>> newPath = r"c:\windows\temp" >>> print(newPath) c:\windows\temp 3.作用:取消转义行为 >>> win_path = 'c:\temp\newdir' >>> print(win_path) # \t成为tab,\n成为换行 c: emp ewdir >>> wpath = r'c:\temp\newdir' >>> print(wpath) c:\temp\newdir >>> wpath 'c:\\temp\\newdir'

格式化输出

1.提示用户输入(多行)数据 2.假定屏幕的宽度为50 ,用户输入的多行数据如下显示(文本内容居中) : +***********************************************************+ + hello world + + great work! + +***********************************************************+ # 练习 1 >>> s1 = ' \tHello World! ' >>> s1.strip() # 删除两端空白字符 'Hello World!' >>> s1.lstrip() 'Hello World! ' >>> s1.rstrip() ' \tHello World!' >>> s2 = 'hao123' >>> s2.center(30) ' hao123 ' >>> s2.center(30, '*') '************hao123************' >>> s2.ljust(30, '#') 'hao123########################' >>> s2.rjust(30, '#') '########################hao123' >>> s2.replace('h', 'H') # 替换 'Hao123' >>> s2.upper() 'HAO123' >>> 'HAO123'.lower() 'hao123' >>> s2.islower() # 字母都是小写的吗 True >>> s2.isdigit() # 所有字符都是数字吗? False >>> s2.startswith('ab') # 是以ab开头吗? False >>> s2.endswith('123') # 是以123结尾吗? True >>> s1.count('l') # 统计l出现的次数 3 >>> s1.index('l') # 第一个l的下标 4 # 练习 2 内建函数 1.string.capitalize() :把字符串的第一个字符大写 2.string.center(width) :返回一个原字符串居中, 并使用空格填充至长度width的新字符串 3.string.count(str, beg=0,end=len(string)) :返回str在string里面出现的次数,如果beg或者end指定则返回指定范围内str出现的次数 1.string.endswith(obj, beg=O,end=len(string)) :检查字符串是否以obj结束,如果beg或者end指定则检查指定的范围内是否以obj结束,如果是,返回True,否则返回False 2.string.islower() :如果string中包含至少一个区分大小写的字符,并且所有这些字符都是小写,则返回True,否则返回False 1.string.strip() :删除string字符串两端的空白 2.string.upper() :转换string中的小写字母为大写 3.string.split(str="", num= string.count(str)) :以str为分隔符切片string ,如果num有指定值,则仅分隔num个子字符串
作者:Vegetable monopoly



模块 subprocess shell

需要 登录 后方可回复, 如果你还没有账号请 注册新账号