【Python教程】07.系统与命令

大纲

系统模块

Python的系统模块主要包括 ossys 模块,这两个是很常用的模块,基本都会引入。
模块导入

import os
import sys

系统常量:获取当前系统相关的信息。
1、当前系统sys.platform

print(sys.platform)

输出:image.png
Python是跨平台的语言,就是说在windows上开发的代码,在linux、macos上也可以运行。
在其他平台开发的语言也能在windows上运行。
但是实际在编写跨平台程序的时候,必然会遇到不同平台不同的解决方式。
这时候就需要获得当前系统来分离出不同平台的代码。

2、Python环境变量sys.versionsys.executablesys.path

print(sys.version.split()[0])   # 获得Python版本
print(sys.executable)           # 获得Python的执行文件
print(sys.path)                 # 获得Python代码的所有目录

输出:
image.png

获得Python的版本号时,一般只要取第一块内容就可以了。可以用于不同版本的处理。
Python的执行文件就是使用的python,结果也验证了我们在使用venv的虚拟环境。
Path目录则是所有的Python代码所在的目录,在运行时会在这些目录下来找到模块
这个列表中包括了我们的开发目录Python自带包目录、以及第三方包目录

3、跨平台符号os.linesepos.sepos.pathsep

print(os.linesep)       # 换行符,Unix为 \n ,Win32为 \r\n
print(os.sep)           # 文件路径分隔符,Unix为 /,Win32为 \
print(os.pathsep)       # 多个文件路径间的分隔符,Unix为 :,Win32为 ;

在遇到需要编写运行不同平台的代码时,这些符号最好使用这些常量。

4、其他不重要的sys.maxsizesys.winveros.curdiros.pardiros.copyright等。

print(sys.maxsize)      # 整数最大值 9223372036854775807
print(sys.winver)       # 主版本号 3.6
print(os.curdir)        # 当前目录 .
print(os.pardir)        # 上一级目录 ..
print(sys.copyright)    # 版权信息

os模块的一个重要的功能就是对文件目录进行操作。我们先来学习文件路径的操作。
文件路径操作os.path【os的子模块】,包含了各种处理文件和文件名的方法。

1、几个常量os.path.sepos.path.pathsepos.path.extsep

print(os.path.sep)      # 路径分隔符 (Unix为 /,Win为 \\)
print(os.path.pathsep)  # 多个路径间的分隔符,多用于环境变量 (Unix为 :, Win为 ;)
print(os.path.extsep)   # 后缀名符号 一般为 .

与os模块差不多。

2、路径组合os.path.join

path = os.path.join('newdir', 'python.txt')

输出:image.png
join的参数是一个不定参数,可以填入无限多个参数,print方法也有同样的方式。
join会将所有的参数组合成一个路径,使用该系统的分隔符。

3、路径分割os.path.splitos.path.dirnameos.path.basenameos.path.splitext

_dir, _file = os.path.split(path)   # 分割成目录和文件
print(_dir)                     # 目录
print(_file)                    # 文件
print(os.path.dirname(path))    # 与_dir一样
print(os.path.basename(path))    # 与_file一样

输出:image.png
split方法将路径分解为目录文件两个。这里文件也可以是最后一级目录
或者也可以使用dirnamebasename方法分别获得目录和文件。

_filename, _ext = os.path.splitext(_file)   # 文件名和扩展名
print(_filename, _ext)

输出:image.png
splitext用于分解出扩展名,也是很常用的一个方法。

4、路径变换os.path.relpathos.path.abspathos.path.commonprefix

print(os.path.relpath(path))    # 获得相对于当前路径的路径
print(os.path.abspath(path))    # 绝对路径

输出:image.png
relpath将路径转化为基于当前目录的相对路径abspath将路径转化为绝对路径

f1 = 'newdir/py/file.txt'
f2 = 'newdir/py/l1/file.txt'
f3 = 'newdir/py/l2/file.txt'
print(os.path.commonprefix([f1, f2, f3]))

输出:image.png
commonprefix可以获得的几个路径【列表传入】的共同前缀

5、判断路径存在os.path.existsos.path.isdiros.path.isfile

print(os.path.exists(path))      # 判断是否存在
print(os.path.isdir(path))       # 判断是否文件夹print(os.path.isfile(path))      # 判断是否文件

exists存在,isdir存在且是文件夹,isfile存在且是文件。

6、文件属性os.path.getatimeos.path.getmtimeos.path.getctimeos.path.getsize

print(os.path.getatime('./os1.py'))     # 访问时间
print(os.path.getmtime('./os1.py'))     # 修改时间
print(os.path.getctime('./os1.py'))     # 创建时间
print(os.path.getsize('./os1.py'))      # 文件大小

文件必须存在,否则报错。
时间返回的是float类型时间戳,文件大小以kb为单位。

文件操作:创建、修改、删除、查看。
1、创建文件夹os.mkdiros.makedirs

os.mkdir('./newdir')     # 创建目录

mkdir只能创建一级目录,必须保证前一级目录os.path.dirname(path)是存在的。
如果不存在,必须使用makedirs

os.mkdir('./newdir2/abc')       # 错误,newdir2文件夹并不存在
os.makedirs('./newdir2/abc')    # 正确,创建多级目录

如果目录已经存在,两个方法都会报错,一般使用前会先判断是否存在。

2、删除目录os.rmdiros.removedirs

os.rmdir('./newdir')            # 删除目录
os.removedirs('./newdir2/abc')  # 删除多级目录

rmdir要删除的目录下必须是空的。
removedirs会从最底层目录开始向上删除,每级目录也都要保证是空的。

3、删除文件os.remove

open('./abc.txt', 'w').close()  # 创建一个文件
os.remove('./abc.txt')  # 删除文件

remove会删除一个文件,文件必须存在

4、文件移动os.rename

os.rename('./abc.txt', './ccc.txt')

第一个参数为要移动的文件,第二个参数为目标地址
要保证要移动文件存在;目标地址要保证目录存在,且该地址不存在。

5、文件列表os.listdir

print(os.listdir('../'))

参数写入一个文件目录,返回该目录下所有文件和目录列表。
image.png
另一种获取文件列表的方式是通过glob模块,使用*作为通配符,找到格式一致的文件。

import glob
print(glob.glob('../*/*.py'))

*匹配任意字符,可以实现比listdir更强大的功能。

6、遍历文件夹os.walk
使用listdir来实现文件夹遍历,只能实现在有规律的文件夹上。
walk可以实现某个文件夹下所有文件的遍历。

for root, dirs, files in os.walk('../06/'):
    for f in files:
        filename = os.path.join(root, f)
        print(filename)

root是当前遍历到的子目录,walk循环会逐层将所有子目录都遍历一遍。
dirs是该子目录下的所有文件夹,比较少使用。
files是该子目录下的所有文件,可以实现文件遍历搜索各种功能。

交互式

Python有两种运行方式:一种是脚本式,就是我们所开发的python文件。
另一种是交互式,主要用于简单的python运行或调试。
image.png
cmd命令行界面中输入python,进入了交互式界面。输入一块代码,马上会显示结果。
交互式虽然比较简单,很难实现复杂的功能,
但也发展出了像Jupyter notebook这样的在数据分析、机器学习方面常用的工具。
关于Jupyter未来有相关课再做介绍。

命令行

脚本运行的方式是命令行
image.png
其实也是执行了venv下的python命令,后面跟上要执行的文件
命令行实际就是使用了一个python命令,它的第一个参数必须是文件。

命令参数:python命令后面除了第一个文件参数,还可以跟上任意参数来方便使用。
Pycharm中添加参数:
右上角点击下拉框,选择Edit Configurations
image.png

输入执行配置名,选择执行文件,最后在Parameters里写入参数。右下角OK保存。
image.png
这里的配置相当于执行了python main.py --dir C:/abc -all

获取参数sys.argv

import sys
print(sys.argv)     # 获取所有参数

返回了一个参数列表,第一个是执行文件,后面的就是我们刚才写入的参数。
下面是通过获取参数来展示输入目录下的文件列表,且在-all时同时输出文件夹。

def listdir(path, with_dir=False):
    result = []
    for f in os.listdir(path):
        if with_dir or os.path.isfile(os.path.join(path, f)):
            result.append(f)
        return result
        
if __name__ == '__main__':
    if sys.argv[1] == '--dir':
        path = sys.argv[2]
        with_dir = len(sys.argv) > 3 and sys.argv[3] == 'all'
        print(listdir(path, with_dir))

更优雅的方式argparse模块。

import argparse
if __name__ == '__main__':
    parser = argparse.ArgumentParser()                      # 开启参数解析
    parser.add_argument('--dir', default='.')               # 必填位置参数
    parser.add_argument('all', nargs='?', default=False)    # 可选参数,默认为False
    args = parser.parse_args()
    print(listdir(args.dir, args.all))

先创建一个参数解析器parser,通过add_argument添加参数定义,最后解析到args中。
添加--dir 位置参数,横杠打头的参数都是位置参数,后面必须跟上参数值。
添加 all 可选参数,nargs=‘?’定义了可选,默认不存在时为False,存在则解析为all。
最后通过parse_args将参数解析出来到变量中,就可以直接使用成员变量的方式调用了。

打包

学习完命令行参数,我们就可以让用户根据设定好的参数进行程序的使用。
但是,这还需要用户安装环境。让用户可以零基础使用我们的程序,就要进行打包

打包模块pyinstaller模块。如果出现安装失败的情况,请先安装wheel模块。

打包命令:先在底部开启命令行模式Terminal
image.png

配置

除了可以通过命令行参数来传递参数,还可以通过配置文件来进行。

配置文件ini文件。
创建一个config.ini配置文件。

[DEFAULT]
dir = C:/Users

[INFO]
x = 1
save = True

[]里面是section,下面的是具体的option

读取配置文件configparser模块。

conf = configparser.ConfigParser()  # 创建对象
conf.read('config.ini')             # 读取文件
print(conf['DEFAULT']['dir'])       # 获取配置
print(int(conf['INFO']['x']))
print(conf['INFO']['save'] == 'True')

输出:image.png

ConfigParser对象,读取配置文件后,就可以直接获取里面的配置。
通过类似字典的方式获取配置[section][option],所有配置获取出来都是字符串

其他获取方式getgetintgetbooleangetfloat

conf.get('DEFAULT', 'dir')       # 获取配置
conf.getint('INFO', 'x')         # int
conf.getboolean('INFO', 'save')  # boolean

与直接获取不同的是,get方法可以进行基础转换。

判断方法has_sectionhas_option

conf.has_section('DEFAULT')     # 是否存在section
conf.has_option('INFO', 'dir')  # 是否存在option

我们发现[INFO][dir]的option是存在的,即第二行代码返回的是True。
这是因为DEFAULT是配置文件的父类,其他所有的section继承自DEFAULT。
与类一样,同样也可以进行复写

配置遍历sectionsoptionsitems

print(conf.sections())          # 返回所有section
print(conf.options('INFO'))     # 返回section下所有options

输出:image.png
sections并没有返回DEFAULT,因为他是父类。
options里也返回了从父类继承的dir。

for group, section in conf.items():
    for key, value in section.items():
        print('conf[{}][{}] = {}'.format(group, key, value))

输出:image.png

循环中的groupsection分别是名称section对象
section对象也有items方法,返回options的内容。上面的代码就打印了所有的配置。

配置修改add_sectionsetremove_optionremove_section

conf.add_section('DEBUG')                   # 添加新section
conf.set('DEBUG', 'y', '1')                 # 添加新option
conf.set('INFO', 'dir', 'C:/Users/lin02')   # 修改option
with open('config.ini', 'w') as f:
    conf.write(f)                           # 写入文件

使用add_sectionset进行添加修改操作,然后write写入文件,一般我们会覆盖原文件。
remove_optionremove_section用于删除。
如果没有进行读取read】操作,上面的方法则可以直接创建一个配置文件。

命令行中添加一个默认值,从配置文件读取。

import argparse
import configparser
if __name__ == '__main__':
    conf = configparser.ConfigParser()   
    conf.read('config.ini')
    default_dir = conf.get('INFO', 'dir')   # 获取默认值   
    parser = argparse.ArgumentParser()   
    parser.add_argument('--dir', default=default_dir)   
    parser.add_argument('all', nargs='?', default=False)   
    args = parser.parse_args()
    print(listdir(args.dir, args.all))

重新打包后,将config.ini放在exe文件同级目录,就可以正常使用了。
image.png
因为我们使用的是相对路径,而程序的相对路径就是exe所在的路径。
有了配置文件,我们的程序就更完善了。

练习

1、编写一个简化版的dir命令。
2、编写一个批量修改文件名的工具,并打包成exe。

  1. 自己创建一个文件夹,里面任意一推的文件。
  2. 给下面的文件批量加一个前缀。
  3. 根据文件创建时间排序,在扩展名前加序号,序号递增。

main.exe --dir C:\abc --prefix hh
xxx.txt => hhxxx1.txt


github: https://github.com/lvancer/course_python

你可能感兴趣的:(python,pycharm,语法,教程)