3.3.2.1 OS 系统操作
在日常使用计算机时,经常需要列出一个文件夹或者目录的内容,创建和删除文件,以及做其他一些比较无聊但是不得不做的“家务活”。在 Python 程序中可以做到同样的事,甚至能做更多的事。这些功能是否能减少你的工作量呢?我们拭目以待。
Python 在模块 os
(操作系统,operating system)中提供了许多系统函数,本章的所有程序都需要导入这个模块。
Python 的 os 模块封装了常见的文件和目录操作,本文只列出部分常用的方法,更多的方法可以查看官方文档。
os 目录操作
方法 | 说明 |
---|---|
os.mkdir | 创建目录 |
os.rmdir | 删除目录 |
os.rename | 重命名 |
os.remove | 删除文件 |
os.getcwd | 获取当前工作路径 |
os.chdir | 修改当前工作目录 |
os.mkdir
创建文件目录。
In [4]: os.mkdir(os.path.join(os.path.abspath('.'), 'testdir'))
os.rmdir
删除文件目录。
In [6]: os.rmdir(os.path.join(os.path.abspath('.'), 'testdir'))
os.rename
重命名文件。如果文件不存在则报错
In [10]: os.rename('test.txt', 'test.py')
os.remove
删除文件,文件不存在时报错
In [13]: os.remove('test.py')
os.getcwd
显示当前程序的工作目录
In [2]: os.getcwd() Out[2]: 'C:\\Users\\Administrator'
os.chdir
改变程序的工作目录
In [2]: os.getcwd() Out[2]: 'C:\\Users\\Administrator' In [3]: os.chdir('C:\\') In [4]: os.getcwd() Out[4]: 'C:\\'
案例一:
显示当前目录中所有的文件
os.path 路径操作
路径: 终点是目标文件,才叫路径,举例:/Users/liaowenxiong/Downloads/SoftWare for Mac/liaowenxiong.txt 这里的终点就是txt文件,这叫路径,路径是可以直接找到目标文件的。
目录: 终点是文件夹 /Users/liaowenxiong/Downloads/SoftWare for Mac,这里的终点SoftWare for Mac是文件夹,这叫目录,目录是无法直接找到目标文件的,目录下可能有N个文件或文件夹
原文链接:路径和目录的区别_文件目录和文件路劲什么区别_liaowenxiong的博客-优快云博客
os.path
模块是跨平台的,即使不打算在平台之间移植自己的程序也应该用 os.path
,好处多多。
操作路径
后文的例子以下面的目录结构为参考,工作目录为 'C:\\Users\\Administrator'
。
方法 | 说明 |
---|---|
os.path.join | 连接目录与文件名 |
os.path.split | 分割文件名与目录 |
os.path.abspath | 获取绝对路径 |
os.path.dirname | 获取路径 |
os.path.basename | 获取文件名或文件夹名 |
os.path.splitext | 分离文件名与扩展名 |
os.path.isfile | 判断给出的路径是否是一个文件 |
os.path.isdir | 判断给出的路径是否是一个目录 |
os.path.exists | 检查文件是否存在 |
In [4]: os.getcwd() Out[4]: 'C:\\Users\\Administrator' In [7]: os.path.abspath('hello.py') Out[7]: 'C:\\Users\\Administrator\\hello.py' In [8]: os.path.abspath('.') Out[8]: 'C:\\Users\\Administrator'
-
os.path.split:分离目录与文件名
-
split()
函数将路径分成两个独立的部分,并返回一个tuple
结果。第二个元素是路径的最后一个元素,第一个元素是它之前的所有元素。 -
join()
函数能将两个或者多个独立部分,拼接为一个路径.
-
In [9]: os.path.split(os.path.abspath('.')) Out[9]: ('C:\\Users', 'Administrator') In [11]: os.path.join('C:\\Users', 'Administrator') Out[11]: 'C:\\Users\\Administrator'
-
os.path.splitext:分离文件名与扩展名
splitext()
类似于split()
,但在扩展分隔符上划分路径,而不是目录分隔符。
In [17]: os.path.splitext('filename.txt') Out[17]: ('filename', '.txt')
案例二:
在测试文件夹下, 给所有的 txt
文件前加上前缀 [前缀]
两个字
检查路径
-
os.path.dirname:获取文件或文件夹的路径
In [7]: os.path.dirname('C:\\Users\\Administrator\\hello.py') Out[7]:'C:\\Users\\Administrator' In [8]: os.path.dirname('C:\\Users\\Administrator\\python') Out[8]: 'C:\\Users\\Administrator' In [9]: os.path.dirname('C:\\Users\\Administrator') Out[9]: 'C:\\Users'
-
os.path.basename:获取文件名或文件夹名
In [10]: os.path.basename('C:\\Users\\Administrator\\hello.py') Out[10]: 'hello.py' In [11]: os.path.basename('/Users/ethan/coding/python') Out[11]: 'python'
-
os.path.isfile/os.path.isdir
In [17]: os.path.isfile('C:\\Users\\Administrator\\hello.py') Out[17]: True In [18]: os.path.isfile('C:\\Users\\Administrator\\hello1.py') Out[18]: False In [20]: os.path.isdir('C:\\Users\\Administrator\\hello1.py') Out[20]: False In [21]: os.path.isdir('C:\\Users\\Administrator') Out[21]: True
案例二:
显示当前目录中所有的目录
Python的listdir()方法返回一个列表,其中包含由path指定的目录中的条目的名称。 列表是任意顺序的。它不包括特殊条目’.‘ 和’..‘,即使它们存在于目录中。
路径可以是类型str或类型字节。如果路径是字节类型,返回的文件名也将是字节类型; 在所有其他情况下,它们将是str类型。 ———————————————— 版权声明:本文为优快云博主「Elvirangel」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。 原文链接:Python中的listdir()函数_python listdir_Elvirangel的博客-优快云博客
In [12]: [x for x in os.listdir('.') if os.path.isdir(x)]
3.3.2.2 sys 模块
系统自身的一些操作
sys模块包括了一组非常实用的服务,内含很多函数方法和变量,用来处理Python运行时配置以及资源,从而可以与前当程序之外的系统环境交互,如:Python解释器。与os模块相比,其更多的在于针对系统环境的交互,而os则操作文件目录。
导入sys模块
首先,打开终端模拟器进入Python解释器或者打开IDE编辑器创建一个新的.py后缀名的Python程序文件。 下面,以解释器中的操作举例:
>>> import sys #导入sys模块 >>> dir(sys) #dir()方法查看模块中可用的方法
sys 常见函数
了解
-
sys.argv
: 命令行参数,包括脚本名称,实现从程序外部向程序传递参数 -
sys.exit([arg])
: 程序中间的退出,arg=0为正常退出 -
sys.path
: 查找模块所在目录的目录名列表 -
sys.modules
:映射模块名字到载入模块的字典 -
sys.platform
: 获取当前系统平台 -
sys.stdin
:标准输入流-一个类文件(file-like)对象 -
sys.stdout
:标准输出流-一个类文件对象 -
sys.stderr
:标准错误流-一个类文件对象 -
sys.getdefaultencoding()
: 获取系统当前编码,一般默认为ascii。 -
sys.setdefaultencoding()
: 设置系统默认编码,需要reload(sys)才能查询看到 -
sys.getfilesystemencoding()
: 获取文件系统使用编码方式,Windows下返回’mbcs’,mac下返回’utf-8’
sys.argv
sys.argv
是命令行参数,包括脚本名称,它的功能可以实现从程序外部向程序传递参数。那么这个过程是如何实现的呢?假设有一个名为test.py
的文件,则可以通过import sys
和print sys.argv[number]
两句来实现。number=0为这个脚本的名字,1,2,…则为命令行下传递的参数。
如test.py脚本内容如下:
import sys print(sys.argv[0]) print(sys.argv[1]) print(sys.argv[2]) print(sys.argv[3])
那么要实现参数传递即可采用>>>python test.py arg1 arg2 arg3
实现。下文会结合sys.path
给出一个示例。上述命令的输出结果为:
test.py arg1 arg2 arg3 sys.exit([arg])
执行至主程序的末尾时,解释器会自动退出。但如果需要中途退出程序,可以调用 sys.exit()
函数来实现。它带有一个可选的整数参数返回给调用它的程序。这意味着你可以在主程序中捕获对sys.exit()
的调用。(0为正常退出,其他为不正常,可抛异常事件供捕获)
sys.exit()
函数运行示例如下:
import sys sys.exit(1) # 直接退出程序 print('hello')
sys.path
sys.path
的功能是获取指定模块搜索路径的字符串集合,可以将写好的模块放在得到的某个路径下,就可以在程序中import时正确找到。
示例:
In [1]: import sys In [2]: sys.path Out[2]: ['', 'C:\\paisen\\Anaconda3\\Scripts', 'C:\\paisen\\Anaconda3\\python36.zip', 'C:\\paisen\\Anaconda3\\DLLs', 'C:\\paisen\\Anaconda3\\lib', 'C:\\paisen\\Anaconda3', 'C:\\Users\\Administrator\\AppData\\Roaming\\Python\\Python36\\site-packages', 'C:\\paisen\\Anaconda3\\lib\\site-packages', 'C:\\paisen\\Anaconda3\\lib\\site-packages\\setuptools-39.1.0-py3.6.egg', 'C:\\paisen\\Anaconda3\\lib\\site-packages\\pip-10.0.1-py3.6.egg', 'C:\\paisen\\Anaconda3\\lib\\site-packages\\win32', 'C:\\paisen\\Anaconda3\\lib\\site-packages\\win32\\lib', 'C:\\paisen\\Anaconda3\\lib\\site-packages\\Pythonwin', 'C:\\paisen\\Anaconda3\\lib\\site-packages\\IPython\\extensions', 'C:\\Users\\Administrator\\.ipython']
可以采用sys.path.append("自定义模块路径")
增加模块搜索路径(也可以用sys.path.insert
进行列表插入)。以上列出的模块目录,在python执行import module_name
时,会依次从上述列出的路径来搜索对应的模块。如有需要手动添加模块,可放入对应的路径中,如无必要建议不要手动添加路径。.
代表当前文件目录。
上问提到的sys.argv
参数传递示例如下:
输入:
import sys print('当前 Python PATH 路径有以下内容:') for path in sys.path: print(path)
输出:
当前 Python PATH 路径有以下内容: F:\进阶部分 F:\进阶部分 C:\paisen\Anaconda3\python36.zip C:\paisen\Anaconda3\DLLs C:\paisen\Anaconda3\lib C:\paisen\Anaconda3 C:\Users\Administrator\AppData\Roaming\Python\Python36\site-packages C:\paisen\Anaconda3\lib\site-packages C:\paisen\Anaconda3\lib\site-packages\setuptools-39.1.0-py3.6.egg C:\paisen\Anaconda3\lib\site-packages\pip-10.0.1-py3.6.egg C:\paisen\Anaconda3\lib\site-packages\win32 C:\paisen\Anaconda3\lib\site-packages\win32\lib C:\paisen\Anaconda3\lib\site-packages\Pythonwin C:\Program Files\JetBrains\PyCharm 2018.2.5\helpers\pycharm_matplotlib_backend
sys.modules
下面部分内容均为演示
sys.modules
是一个全局字典,该字典是python启动后就加载在内存中。每当导入新的模块时,sys.modules
将自动记录该模块。当第二次再导入该模块时,python会直接到字典中查找,从而加快了程序运行的速度。它拥有字典所拥有的一切方法。
示例:
import sys print(sys.modules.keys()) # 列出所有的模块名 print(sys.modules['os']) # 列出指定模块如os模块所在路径 print(sys.modules.values()) # 列出所有模块所在路径
sys.platform
sys.platform
语句用于查看当前平台,如win32、linux2等。
In [28]: sys.platform Out[28]: 'win32'
3.3.2.3 random
3.3.2.4 time
3.3.2.5 json
https://blog.youkuaiyun.com/weixin_43631296/article/details/105253434?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522168750519416800182166294%2522%252C%2522scm%2522%253A%252220140713.130102334..%2522%257D&request_id=168750519416800182166294&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2~all~top_positive~default-1-105253434-null-null.142^v88^control_2,239^v2^insert_chatgpt&utm_term=json.load&spm=1018.2226.3001.4187
3.3.2.6 logging(日志)
日志记录是程序员工具箱中非常有用的工具。它可以帮助您更好地理解程序的流程,并发现您在开发过程中可能没有想到的场景。
日志为开发人员提供了额外的一组眼睛,这些眼睛不断关注应用程序正在经历的流程。它们可以存储信息,例如访问应用程序的用户或IP。如果发生错误,那么通过告诉您程序在到达发生错误的代码行之前的状态,它们可以提供比堆栈跟踪更多的见解。
通过从正确的位置记录有用的数据,您不仅可以轻松地调试错误,还可以使用数据分析应用程序的性能以规划扩展或查看使用模式以规划营销。
Python提供了一个日志系统作为其标准库的一部分,因此您可以快速将日志记录添加到您的应用程序中。在本文中,您将了解为什么使用此模块是向应用程序添加日志记录以及如何快速入门的最佳方式,您将了解一些可用的高级功能。
Logging模块
Python中的日志记录模块是一个随时可用且功能强大的模块,旨在满足初学者和企业团队的需求。它被大多数第三方Python库使用,因此您可以将日志消息与这些库中的日志消息集成,以为您的应用程序生成同类日志。
将记录添加到Python程序就像这样简单:
import logging
导入日志记录模块后,您可以使用称为“logger”的内容来记录您要查看的消息。默认情况下,有5个标准级别指示事件的严重性。每个都有一个相应的方法,可用于记录该严重级别的事件。按严重程度增加的顺序定义的级别如下:
-
DEBUG
-
信息 info
-
警告 warning
-
错误 error
-
危急 critical
日志记录模块为您提供了一个默认记录器,使您无需进行太多配置即可开始使用。可以调用每个级别的相应方法,如以下示例所示:
import logging logging.debug('这里是调试信息') logging.info('这里是详情信息') logging.warning('这里是警告信息') logging.error('这里是错误信息') logging.critical('这里是危机信息')
上述程序的输出如下所示:
WARNING:root:这里是警告信息 ERROR:root:这里是错误信息 CRITICAL:root:这里是危机信息
输出显示每条消息之前的严重性级别root
,即日志记录模块为其默认记录器提供的名称。(记录器将在后面的章节中详细讨论。)此格式显示由冒号(:
)分隔的级别,名称和消息,是默认的输出格式,可以配置为包括时间戳,行号和其他内容细节。
请注意,并没有记录debug()
和info()
消息。这是因为,默认情况下,日志记录模块会记录严重性级别为WARNING
或更高的邮件。您可以通过将日志记录模块配置为根据需要记录所有级别的事件来更改它。您还可以通过更改配置来定义自己的严重性级别,但通常不建议这样做,因为它可能会导致您可能正在使用的某些第三方库的日志混淆。
基本配置
您可以使用该方法配置日志记录:basicConfig(**kwargs)
一些常用的参数basicConfig()
如下:
-
level
:根记录器将设置为指定的严重性级别。 -
filename
:这指定文件。 -
filemode
:如果filename
给定,则以此模式打开文件。默认值为a
,表示追加。 -
format
:这是日志消息的格式。
通过使用该level
参数,您可以设置要记录的日志消息级别。这可以通过传递类中可用的一个常量来完成,这将允许记录该级别或更高级别的所有日志记录调用。这是一个例子:
import logging # 1.1 设置默认日志等级 logging.basicConfig(level=logging.DEBUG) logging.debug('hello logger')
输出内容:
DEBUG:root:hello logger
DEBUG
现在将记录 DEBUG
级别或更高级别的事件。
同样,对于记录到文件而不是控制台,filename
并且 filemode
可以使用,您可以使用确定消息的格式 format
。以下示例显示了所有三个的用法:
import logging # 1.2 配置写入到文件 logging.basicConfig(filename='app.log', filemode='w', format='%(name)s - %(levelname)s - %(message)s', level=logging.DEBUG) logging.warning('这条信息将被记录到文件')
输出内容:
root - WARNING - 这条信息将被记录到文件
该消息将如下所示,但将写入名为app.log
而不是控制台的文件。filemode设置为w
,这意味着每次basicConfig()
调用日志文件都以“写入模式”打开,程序的每次运行都将重写该文件。filemode的默认配置a
是append。
您可以使用更多参数进一步自定义根记录器basicConfig()
,可在此处找到。
应该注意,basicConfig()
只有在之前没有配置根记录器的情况下,调用配置根记录器才有效。基本上,这个函数只能调用一次。
debug()
,info()
,warning()
,error()
,和critical()
也称basicConfig()
自动无参数,如果它以前没有叫。这意味着在第一次调用上述函数之一后,您无法再配置根记录器,因为它们会在basicConfig()
内部调用该函数。
默认设置basicConfig()
是将记录器设置为以下列格式写入控制台:
ERROR:root:This is an error message
格式化输出
虽然您可以将任何可以表示为字符串的变量作为消息传递给您的日志,但是有一些基本元素已经成为其中的一部分,LogRecord
并且可以轻松添加到输出格式中。如果要将进程ID与级别和消息一起记录,可以执行以下操作:
import logging logging.basicConfig(format='%(process)d-%(levelname)s-%(message)s') logging.warning('This is a Warning') 18472-WARNING-This is a Warning
format
可以使用LogRecord
您喜欢的任何排列中的属性字符串。可以在此处找到可用属性的完整列表。
这是另一个可以添加日期和时间信息的示例:
import logging logging.basicConfig(format='%(asctime)s - %(message)s', level=logging.INFO) logging.info('Admin logged in') 2018-07-11 20:12:06,288 - Admin logged in
%(asctime)s
增加了创造时间LogRecord
。可以使用datefmt
属性更改格式,该属性使用与datetime模块中的格式化函数相同的格式化语言,例如time.strftime()
:
import logging logging.basicConfig(format='%(asctime)s - %(message)s', datefmt='%d-%b-%y %H:%M:%S') logging.warning('Admin logged out') 12-Jul-18 20:53:19 - Admin logged out
你可以在这里找到指南。
记录变量数据
在大多数情况下,您可能希望在日志中包含应用程序中的动态信息。您已经看到日志记录方法将字符串作为参数,并且在单独的行中使用可变数据格式化字符串并将其传递给log方法似乎很自然。但实际上,这可以通过使用消息的格式字符串并将变量数据作为参数附加来直接完成。这是一个例子:
import logging name = 'John' logging.error('%s raised an error', name)
类和函数
到目前为止,我们已经看到了一个名为默认记录器root
,用于通过日志模块,只要其功能被直接称为是这样的:logging.debug()
。您可以(并且应该)通过创建Logger
类的对象来定义自己的记录器,尤其是在应用程序具有多个模块的情况下。我们来看看模块中的一些类和函数。
日志记录模块中定义的最常用类如下:
-
Logger:这是一个类,其对象将直接在应用程序代码中用于调用函数。
-
LogRecord:记录器自动创建
LogRecord
具有与记录事件相关的所有信息的对象,例如记录器的名称,功能,行号,消息等。 -
Handler:处理程序将
LogRecord
控制器或文件发送到所需的输出目标。Handler
对于像的子类的碱StreamHandler
,FileHandler
,SMTPHandler
,HTTPHandler
,等等。这些子类将日志记录输出发送到相应的目标,如sys.stdout
磁盘文件。 -
Formatter:您可以通过指定列出输出应包含的属性的字符串格式来指定输出的格式。
其中,我们主要处理Logger
类的对象,这些对象使用模块级函数进行实例化logging.getLogger(name)
。getLogger()
使用相同的多次调用 name
将返回对同一 Logger
对象的引用,这使我们无法将记录器对象传递到需要它的每个部分。这是一个例子:
import logging logger = logging.getLogger('example_logger') logger.warning('This is a warning')
输出内容:
This is a warning
同样,与根记录器不同,无法使用自定义记录器进行配置basicConfig()
。您必须使用处理程序和格式化程序对其进行配置:
使用 Handler
当您想要配置自己的记录器并在生成日志时将日志发送到多个位置时,处理程序就会出现。处理程序将日志消息发送到已配置的目标(如标准输出流或文件或HTTP)或通过SMTP发送到您的电子邮件。
您创建的记录器可以有多个处理程序,这意味着您可以将其设置为保存到日志文件并通过电子邮件发送。
与记录器一样,您也可以在处理程序中设置严重性级别。如果要为同一记录器设置多个处理程序但希望每个处理程序具有不同的严重性级别,这将非常有用。例如,您可能希望将具有级别WARNING
及更高级别的日志记录到控制台,但是具有级别ERROR
及更高级别的所有内容也应保存到文件中。这是一个执行该操作的程序:
# logging_example.py import logging # Create a custom logger logger = logging.getLogger(__name__) # Create handlers c_handler = logging.StreamHandler() f_handler = logging.FileHandler('file.log') c_handler.setLevel(logging.WARNING) f_handler.setLevel(logging.ERROR) # Create formatters and add it to handlers c_format = logging.Formatter('%(name)s - %(levelname)s - %(message)s') f_format = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s') c_handler.setFormatter(c_format) f_handler.setFormatter(f_format) # Add handlers to the logger logger.addHandler(c_handler) logger.addHandler(f_handler) logger.warning('This is a warning') logger.error('This is an error')
输出内容:
__main__ - WARNING - This is a warning __main__ - ERROR - This is an error
在这里,logger.warning()
创建一个LogRecord
包含事件的所有信息并将其传递给它拥有的所有处理程序:c_handler
和f_handler
。
c_handler
是一个StreamHandler
带有级别WARNING
并从中获取信息LogRecord
以生成指定格式的输出并将其打印到控制台。f_handler
是一个FileHandler
有级别的 ERROR
,它忽略LogRecord
了它的级别WARNING
。
当logger.error()
调用时,c_handler
行为与以前完全相同,并f_handler
获得a LogRecord
级别ERROR
,因此它继续生成输出c_handler
,但不是将其打印到控制台,而是以这种格式将其写入指定的文件:
输出内容:
2018-08-03 16:12:21,723 - __main__ - ERROR - This is an error
将与 __name__
变量对应的记录器的名称记录为 __main__
,这是 Python 分配给执行开始的模块的名称。如果此文件由某个其他模块导入,则该 __name__
变量将对应于其名称 logging_example
。这是它的样子:
# run.py import logging_example
输出内容:
logging_example - WARNING - This is a warning logging_example - ERROR - This is an error
保持冷静并阅读日志
记录模块被认为非常灵活。它的设计非常实用,应该适合您的开箱即用。您可以将基本日志记录添加到一个小项目中,或者如果您正在处理一个大项目,则可以创建自己的自定义日志级别,处理程序类等。
如果您还没有在应用程序中使用日志记录,那么现在是开始的好时机。完成后,日志记录肯定会消除开发过程中的大量摩擦,并帮助您找到将应用程序提升到新的水平的机会。