Python 快速入门(第3版)11-13章 读书笔记

《Python 快速入门(第3版)》娜奥米·赛德

 11.1.2 命令行参数

argvtest.py内容如下

import sys
def main():
    print(sys.argv)
main()

命令行参数会以字符串列表的形式存入sys.argv中

# python argvtest.py arg1 arg2 arg3
['argvtest.py', 'arg1', 'arg2', 'arg3']

11.1.3 脚本输入/输出的重定向

一般来说,命令行 
​​python script.py arg1 arg2 arg3 < infile > outfile​​
的运行效果是,把input或sys.stdin的所有操作都定向为来自infile,把print或sys.stdout的所有操作都定向到outfile。这种效果如同是将sys.stdin设为只读模式('r')的infile,将sys.stdout设为只写('w')模式的outfile。以下命令效果一致,
注:把">"改为“>>”将使输出结果追加至outfile末尾,而不是会覆盖掉输出文件。

例,replace.py内容如下

import sys
def main():
    contents = sys.stdin.read()
    sys.stdout.write(contents.replace(sys.argv[1],sys.argv[2]))

main()

infile.txt内容如下

one two zero
zero three four
a s dfgh aaaaa

执行 python3 replace.py zero 0 <infile.txt> outfile.txt,outfile.txt内容如下

one two 0
0 three four
a s dfgh aaaaa

继续执行 python3 replace.py a A <infile.txt>> outfile.txt

# cat outfile.txt
one two 0
0 three four
a s dfgh aaaaa
one two zero
zero three four
A s dfgh AAAAA

结合管道符,如下命令会把 "a"替换为"A", "one"替换为"1"输出到outfile.txt

[root@k8s-node2 ~]# python3 replace.py a A <infile.txt | python3 replace.py one 1 > outfile.txt
[root@k8s-node2 ~]# cat outfile.txt
1 two zero
zero three four
A s dfgh AAAAA
[root@k8s-node2 ~]#

11.1.4 argparse模块

argparse模块_wy_hhxx

11.1.5 fileinput模块的使用

fileinput模块_wy_hhxx

11.2 让脚本在UNIX下直接运行

在脚本文件的第一行加入以下命令,并将文件属性修改正确,即chmod +x <filename>
​​#!/usr/bin/env python​​

我的测试环境使用的python3且非默认,所以需要使用 ​​#!/usr/bin/env python​​3

[root@k8s-node2 ~]# ls -l test1.py
-rwxr-xr-x 1 root root 333 Jul  3 12:01 test1.py
[root@k8s-node2 ~]# ./test1.py
in decorate function, decorating myfunction
Executing myfunction
hello
[root@k8s-node2 ~]#

也可以使用python3的执行路径

[root@k8s-node2 ~]# whereis python3
python3: /usr/local/python3 /usr/local/python3/bin/python3.9 /usr/local/python3/bin/python3.9-config /usr/local/python3/bin/python3
[root@k8s-node2 ~]#

尝试在脚本开头加上如下任意一行,都可以直接执行
#!/usr/bin/env python​​3
#!/usr/local/python3/bin/python3.9
#!/usr/local/python3/bin/python3

11.5 程序和模块

将脚本代码和模块结合在一起是很简单的,也就是在主控函数之外加上以下条件测试:

​​if __name__ == '__main__':
    main()
    else:
        # 本模块的初始化代码​​


如果被作为脚本调用,运行时的当前模块名称将会是__main__,于是会调用主控函数main。如果条件测试已导入交互式会话或其他模块中,则模块名称将会是其文件名。

12.2 路径和路径名

12.2.2 当前工作目录

os模块
os.curdir  #返回'.'
os.getcwd()  #返回当前工作路径 pwd
os.chdir('somepath')  #cd xxx
os.listdir(os.curdir)  #ls

>>> import os
>>> os.curdir
'.'
>>>
>>> os.getcwd()
'/root'
>>>
>>> os.chdir('/opt')
>>> os.getcwd()
'/opt'
>>> os.listdir(os.curdir)
['rh', 'containerd', 'cni']
>>>
>>> os.listdir('/opt')
['rh', 'containerd', 'cni']
>>>

12.2.3 用pathlib模块访问目录

>>> import pathlib
>>> pathlib.Path()
PosixPath('.')
>>> cur_path =  pathlib.Path()
>>> cur_path.cwd()
PosixPath('/opt')
>>>

pathlib不提供像os.chdir()那样改变当前目录的函数,但可以通过创建path对象来新建文件夹

12.2.4 路径名的处理

os.path.join函数将参数解释为一系列的目录名或文件名
os.path.split函数将返回由两个元素组成的元组,将路径拆分为文件名(路径尾部的单个文件或目录名称,basename)和其余部分
os.path.dirname函数只返回路径部分
os.path.basename函数只返回路径中的文件名
os.path.splitext函数可以处理以句点标识的文件扩展名

>>> import os
>>> os.path.join('bin','utils','disktools')
'bin/utils/disktools'
>>>
>>> os.path.split('/bin/utils/disktools/')
('/bin/utils/disktools', '')
>>> os.path.split('/bin/utils/disktools')
('/bin/utils', 'disktools')
>>>
>>> os.path.dirname('/bin/utils/disktools/')
'/bin/utils/disktools'
>>> os.path.dirname('/bin/utils/disktools')
'/bin/utils'
>>> os.path.basename('/bin/utils/disktools')
'disktools'
>>>
>>> os.path.splitext('/bin/utils/disktools/pic.jpg')
('/bin/utils/disktools/pic', '.jpg')
>>>

12.2.5 用pathlib处理路径名

>>> from pathlib import Path
>>> cur_path = Path()
>>> print(cur_path.joinpath('bin','utils','disktools'))
bin/utils/disktools
>>>
>>>
>>> a_path = Path('bin','utils','disktools')
>>> a_path
PosixPath('bin/utils/disktools')
>>>
>>> a_path.parts
('bin', 'utils', 'disktools')
>>>
>>> a_path.name
'disktools'
>>> a_path.parent
PosixPath('bin/utils')
>>> a_path.suffix
''
>>>
>>> b_path = Path('/bin/utils/disktools/pic.jpg')
>>>
>>> b_path.suffix
'.jpg'
>>>

os.path和pathlib.Path比较

os.pathpathlib.Path
os.path.join('bin','utils','disktools')
返回str

a_path = Path('bin','utils','disktools')

返回<class 'pathlib.PosixPath'>

os.path.split('/bin/utils/disktools/')

返回tuple

a_path.parts

返回tuple

os.path.dirname('/bin/utils/disktools/')

返回str

a_path.parent
返回<class 'pathlib.PosixPath'>

os.path.basename('/bin/utils/disktools')

返回str

a_path.name

返回str

os.path.splitext('/bin/utils/disktools/pic.jpg')

返回str

a_path.suffix

返回str

12.2.6 常用变量和函数

最基本的常量就是os.curdir和os.pardir,分别定义了操作系统用于表示目录和父目录的路径符号。

os.name大多数Windows版本都被识别为'nt'
在运行OS X的Mac机器上,以及Linux/UNIX系统中,返回值将为posix

>>> os.curdir
'.'
>>> os.pardir
'..'
>>> os.name
'posix'
>>>

12.3 获取文件信息

以下函数接收路径信息,返回True/False
os.path.exists 
os.path.isfile
os.path.isdir
os.path.islink
os.path.ismount
os.path.isabs 是否为绝对路径

os.path.samefile(path1, path2) 当且仅当参数中的两个路径指向同一个文件时,才会返回True

os.path.getsize(path) 返回路径名大小
os.path.getmtime(path) 最后修改时间
os.path.getatime(path) 最后访问时间

12.4 文件系统的其他操作
(1)os.listdir 获取目录中的文件列表
说明:Python在os.listdir返回的文件列表中,不包含os.curdir和os.pardir标识符

在glob模块中有个glob函数能够扩展路径名中的Linux/UNIX  shell风格的通配符和字符序列,返回当前工作目录中匹配的文件。“*”将匹配任意字符序列,“?”匹配任意单个字符,字符序列(如[h,H]或[0-9])则会匹配序列中的任意单个字符:

>>> import glob
>>> glob.glob("*.cfg")
['original-ks.cfg', 'anaconda-ks.cfg']
>>> glob.glob("sole?.tst")
['sole1.tst', 'sole2.tst']
>>>

(2)用os.rename可以重命名/移动文件或目录
(3)用os.remove可以删除文件
         用os.rmdir可以删除空目录
         如果要删除非空目录,请使用shutil.rmtree函数,它能以递归方式删除目录树中的所有文件

补充:shutil模块中的copytree函数,能够递归地复制目录及其子目录下的所有文件,文件的权限和状态信息(即访问/修改时间)都予以保留。

>>> os.rmdir('testdir/1/2')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
OSError: [Errno 39] Directory not empty: 'testdir/1/2'
>>>
>>> import shutil
>>> shutil.rmtree('testdir')
>>>

(4)用os.makedirs或os.mkdir创建目录
说明:os.makedirs会连同必要的中间目录一起创建,但os.mkdir不会

pathlib提供的其它文件操作
(1)以上提到的大多数操作,Path对象都具备同样功能的方法,但还是有一些区别。iterdir方法类似于os.path.listdir函数,但返回的是路径迭代器而不是字符串列表

>>> new_path = Path('/opt')
>>> new_path.iterdir()
<generator object Path.iterdir at 0x7f520bf3e820>
>>> list(new_path.iterdir())
[PosixPath('/opt/rh'), PosixPath('/opt/containerd'), PosixPath('/opt/cni')]
>>>

(2)用Path对象的rename方法,可以重命名(移动)文件和目录

>>> new_path = Path('mymath_update.py')
>>> old_path = Path('mymath.py')
>>> old_path.rename(new_path)
PosixPath('mymath_update.py')
>>>
>>> cur_path = Path('./')
>>> list(cur_path.iterdir())
[PosixPath('addlinenum.py'), PosixPath('drop2hash.py'), PosixPath('linestatistics.py'), PosixPath('replace.py'), PosixPath('mymath_update.py')]
>>>

(3)要移除或删除数据文件,请使用unlink方法,不能用unlink方法来删除目录
         要删除目录请使用rmdir方法,它只删除空目录

>>> new_path
PosixPath('mymath_update.py')
>>> new_path.unlink()
>>> list(cur_path.iterdir())
[PosixPath('addlinenum.py'), PosixPath('drop2hash.py'), PosixPath('linestatistics.py'), PosixPath('replace.py')]
>>>

(4)要通过path对象创建目录,请使用path对象的mkdir方法。如果调用时带了parents=True参数,mkdir方法就会创建必要的中间目录。否则,就会在中间目录不存在时引发FileNotFoundError

>>> new_path = Path('/root/newdir1/newdir2/')
>>> new_path.mkdir()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/local/python3/lib/python3.9/pathlib.py", line 1313, in mkdir
    self._accessor.mkdir(self, mode)
FileNotFoundError: [Errno 2] No such file or directory: '/root/newdir1/newdir2'
>>>
>>> new_path.mkdir(parents=True)

[root@k8s-node2 ~]# ls -ld /root/newdir1/newdir2/
drwxr-xr-x 2 root root 6 Jul  3 17:43 /root/newdir1/newdir2/
[root@k8s-node2 ~]#

 

文件系统属性值和函数汇总

 

pathlib部分属性和方法

 

13.1 打开文件及file对象

open不会读取文件中的内容,而是返回一个file对象,可用于访问被打开的文件。file对象将会对文件及读写位置进行跟踪记录。
第一次调用readline将返回file对象的第一行,包括第一个换行符在内。

13.2 关闭文件

>>> file_object = open("myfile", 'r')
>>> line = file_object.readline()
>>> file_object.close()

利用上下文管理器和with关键字:

>>> with open("myfile", 'r') as file_object:
...     line = file_object.readline()
...     print(line)
...
2022-7-3

>>>

13.4 读写文本及二进制数据的函数

readline将从file对象中读取并返回一行数据,包括行尾的换行符。如果文件中没有数据可读了,readline将返回空字符串

【例1】使用readline计算文本文件中的文本行数

file_object = open("myfile",'r')
count = 0
while file_object.readline() != "":
    count = count + 1
print(count)
file_object.close()

readlines方法将读取文件中的所有行,并作为字符串列表返回(每行尾部的换行符仍然保留)

【例2】使用readline计算文本文件中的文本行数

file_object = open("myfile",'r')
print(len(file_object.readlines()))
file_object.close()

注意:如果要对一个大型文件统计行数,readlines方法可能会导致计算机内存不足,因为它会一次性将整个文件读入内存。

与readline和readlines方法对应的写入方法是write和writelines。
注意,不存在writeline方法。

write方法将写入一个字符串,如果字符串中包含了换行符,则可以一次写入多行。
write方法在把参数字符串写入完毕后,不会再输出换行符。

writelines方法的参数是字符串列表,将字符串逐个写入file对象,但不会写入换行符。如果列表中的字符串以换行符结尾,则它们将被写成多行,否则在文件中就会紧紧连在一起。

>>> myfile = open("myfilewrite",'w')
>>> myfile.write('Hello')
5
>>> myfile.write('Hello')
5
>>> myfile.write('Hi\nHi\nHi')
8
>>> myfile.writelines(['One','Two','Three'])
>>> myfile.writelines(['1\n','Two\n','Three'])
>>>
-------------------------------------------------
[root@k8s-node2 pydir]# ls -l myfilewrite
-rw-r--r-- 1 root root 0 Jul  3 19:24 myfilewrite
[root@k8s-node2 pydir]#
-------------------------------------------------
>>> myfile.close()
>>>
-------------------------------------------------
[root@k8s-node2 pydir]#
[root@k8s-node2 pydir]# ls -l myfilewrite
-rw-r--r-- 1 root root 40 Jul  3 19:26 myfilewrite
[root@k8s-node2 pydir]# cat myfilewrite
HelloHelloHi
Hi
HiOneTwoThree1
Two
Three[root@k8s-node2 pydir]#

不过writelines是readlines的精确逆操作,可以对readlines返回的列表直接使用writelines,将写入一个与readlines读入的文件完全相同的文件。
假设有一个文本文件myfile.txt,以下代码将为其创建名为myfilecopy.txt的精确副本:

>>> input_file = open("myfile.txt", 'r')
>>> lines = input_file.readlines()
>>> input_file.close()
>>> output = open("myfilecopy.txt", 'w')
>>> output.writelines(lines)
>>> output.close()
>>>

13.5 用pathlib读写文件

用Path对象来读写文本文件不需要执行打开或关闭操作。
限制:无法用Path的方法追加数据,因为其写入操作会把现有数据全部替换掉。

>>> from pathlib import Path
>>> p_text = Path('my_text_file')
>>> p_text.write_text('Some contents.')
14
>>> p_text.read_text()
'Some contents.'
>>>

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值