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个子字符串