黑马python入门(4):python基础(序列,异常,操作文件,模块包,日志调试信息)
python在线手册 https://docs.python.org/zh-cn/3/
序列
str
- 声明:test_str=”abcedf” 也可以保留字符串里面的格式来
test_str=””“
<html>
<title>\r\n测试标题</title>
<body>
<span>hello world</span>
</body>
</html>"
””“
- 长度: len(test_str)
- 元素增: join() 分隔符.join(字符串1,字符串2) 或者 字符串1+ 字符串2
- 元素减:del(test_str)
- 元素改:test_str = “bcdef”
- 元素查: find()来找 还不会报错 in not也可以判断是否存在 但是不如find方便
- 元素输出: test_str[2]
- 元素切割 :test_str[1:5]
- 遍历:for v in test_str:就可以
- 排序: 没有 但是可以转成list类型然后排序就好 再用join拼接成字符串就好
tuple
- 本质:一个无法修改的数字索引数组
- 声明:test_tuple=(1, 2, 3, 4, 5) 小括号声明 注意 声明一个元素的元组 的格式有点变化 test_tuple=(1,)
- 长度: len(test_tuple)
- 元素增: 固定无法操作
- 元素减:固定无法操作
- 元素改:固定无法操作
- 元素查: in not in 来判断是否内容是否在tuple中存在 但是无法确定位置 官方使用index()来确定位置下标但是报错 还是用自己的index_plus()来解决吧
- 元素输出: test_tuple[2] 这是中括号 而不是元组声明的小括号
- 元素切割 :test_tuple[1:5]
- 遍历:for v in aa_tuple:就可以
- 排序:固定无法操作
小知识:序列查找函数index()和index_plus
index()是查找序列元素并返回找到的元素下标的函数 但是美中不足是 找不到却会报错 导致整个代码的崩溃
不知道其他人是怎么解决这个问题的 我用异常来控制报错暂时解决这个问题
def index_plus(ob, __value): """ :param ob: 要查找的序列 :param __value: 要找的内容 :return: int 找不到返回-1 找的到返回下标 function:index的升级版 解决了找不到报错的问题 """ try: temp1 = ob.index(__value) except: temp1 = -1 else: pass finally: return temp1
import zjl aa_tuple = (1, 2, 3, 4, 5, 6, 7, 8, 9) print(zjl.index_plus(aa_tuple,8)) # 7 print(zjl.index_plus(aa_tuple,10)) # -1
list
- 本质:一个数字索引数组
- 声明:test_list=[1, 2, 3, 4, 5]
- 长度: len(test_tuple)
- 元素增:
- test_list.append(新元素)->自动在list末尾添加新元素 实际上等于test_list.insert(len(test_list), 新元素) insert是可以在list任何位置插入新元素的
- list.insert(插入的下标,插入的元素内容)
- 元素减:
- list.pop(删除的元素下标)
- list.remove(删除元素的内容)
- list.pop(len(list)-1)删除末尾的元素
- 元素改:test_list[2] = 23
- 元素查: in not in 来判断是否内容是否存在 但是无法确定位置 使用index_plus()来确定位置下标
- 元素输出: test_list[2] 这是中括号 而不是元组声明的小括号
- 元素切割 :test_list[1:5]
- 遍历:for v in test_list:就可以
- 排序:list.sort() list.reverse()
- 复制 test_list.copy() 因为列表字典这些都是传地址的 所以为了不干扰到原始的列表字典 只能用命令复制一个和原始列表字典一样的变量 但是内存地址完全独立 这样我们修改新的变量不会影响到原始数据
- 清空 test_list.clear()
dict
- 本质:一个非数字索引的table 不能是数字索引 是数字索引就是set了
- 声明:test_dict=(“name”:”zjl”,
“age”:18,
“sex”:True,
“adress”:”shandong”}
- 长度: len(test_dict)
- 元素增: test_dict[“id”] = 00023
- 元素减:test_dict.pop(要删除的元素的key)
- 元素改:test_dict[“id”] = 00024
- 元素查: in not in 来判断是否内容是否存在 但是无法确定位置 使用index_plus()来确定位置下标
- 元素输出: test_dict[2] 这是中括号 而不是元组声明的小括号
- 遍历:for k, v in test_dict.items():就可以 注意items返回的是[(”name”,”zjl”), (”age”,18), (”sex”,True), (”adress”,”shandong”)]
- 排序:只能转成list 然后list.sort()排序了 实际上字典的元素本来就没什么顺序
- 合并: 2字典合并为一个 test_dict.update(新字典) 如果两个字典的Key有冲突 后面的字典会覆盖前面的
- 复制 test_dict.copy() 因为列表字典这些都是传地址的 所以为了不干扰到原始的列表字典 只能用命令复制一个和原始列表字典一样的变量 但是内存地址完全独立 这样我们修改新的变量不会影响到原始数据
- 清空 空字典 test_dict.clear()
set
- 本质:一个元素内容不重复的集合 没有key 无论是数字key还是非数字key 并且集合的元素必须是不可变类型就是说 集合内必须是数字 字符串 元组这种不可变元素 一般是用来求交集并集差集的
- 声明:test_set=(“name”, ”zjl”, 18, (12, 34)} 或者 set(字符串列表元素或者range()) test_set=([“name”, ”zjl”, 18, (12, 34)])
- 长度: len(test_set)
- 元素增: test_set.add(元素)
- 元素减:test_set.discard(删除元素内容)
- 元素改:没有Key来标识每个元素 无法对集合的元素进行修改 除非你重新声明 无法类似 test_dict[0] = 11 XXX
- 元素查: in not in 来判断是否内容是否存在
- 元素输出: 没有Key来标识每个元素 无法
- 遍历:for v in test_set就可以
- 排序:只能转成list 然后list.sort()排序了
- 交集并集差集: & | -
print({1,2} & {2,3,4}) # {2} print({1,2} | {2,3,4}) # {1, 2, 3, 4} print({1,2} - {2,3,4}) # {1}
- 复制 test_set.copy() 因为这些都是传地址的 所以为了不干扰到原始的列表字典 只能用命令复制一个和原始列表字典一样的变量 但是内存地址完全独立 这样我们修改新的变量不会影响到原始数据
- 清空 空字典 test_set.clear()
https://www.cnblogs.com/hukey/p/9242339.html
序列的公共方法和属性
- * +
- in not in
- len()
- del()
- max() min() 字典的是获取Key的最大最小
异常
完整的异常处理结构
import traceback
import logging # 导入日志模块
logger = logging.getLogger("traceback_test") # 配合 traceback.format_exc 输出更详细的情况
logging.basicConfig(level=logging.DEBUG, format="%(asctime)s,%(msecs)d %(levelname)-8s [%(filename)s:%(lineno)d] %(message)s",
datefmt="%d-%m-%Y:%H:%M:%S")
try: # ==================主代码============================= # a = 1/a raise Exception("自定义异常抛出") # 自己抛出异常 可以自定义个异常类 也可以不用想太多直接用这个方式即可 except ValueError as e: # 同时应对多种异常的写法 logging.debug("数字格式异常") logging.debug(repr(e)) # 返回普通的异常信息,包括异常信息的类型 # traceback.print_tb(sys.exc_info()[2]) logger.error(traceback.format_exc(limit=3)) # 输出更多的反馈信息 except ArithmeticError as e: # 同时应对多种异常的写法 logging.debug("算术异常") logging.debug(repr(e)) # 返回较全的异常信息,包括异常信息的类型 # logging.debug(str(traceback.print_tb(sys.exc_info()[2]))) logger.error(traceback.format_exc(limit=3)) # 输出更多的反馈信息 except (ValueError, ArithmeticError): # 同时应对多种异常的写法 logging.debug("程序发生了数字格式异常、算术异常之一") except Exception as e: # Exception as e 放在else之前表示 如果上面都没找到错误应对 那么剩下的异常都归这里 # 输出错误信息 但是并没有太详细 更加详细复杂的错误反馈需要用到 traceback 模块 logging.debug(repr(e)) # 返回较全的异常信息,包括异常信息的类型 # traceback.print_tb(sys.exc_info()[2]) logger.error(traceback.format_exc(limit=3)) # 输出更多的反馈信息 else: logging.debug("无异常") # 没发生异常就跳转到这里 finally: logging.debug("不管有无异常都要执行这") # 不管有无异常都要执行这
异常处理的原理
理解异常类型
异常其实都是一个类 这些异常的关系是如下
所有异常的父类都是BaswException类 常见的细化的类都是BaswException类的子类Exception类的子类 我们常用的自定义异常类也要以Exception为父类才可以
平时代码里面出现的异常都是这些底层的子类的实例而已
异常运行的流程
首先Python解释器 遇到的错误 就是抛出一个异常 我们用try except 结构来接收这个异常的实例 然后根据异常实例的类型的不同 有针对性的进行处理
定义自己的异常类
1.命名是大坨峰法
2.父类都是Exception
3.try except里面可以添加自定义类型来针对处理了 如果不需要这样 就不用自定义异常类了 直接Exception的实例就可以了
class SignFailError(Exception): """ 签到失败 """ # 自定义异常类型的初始化 def __init__(self, value): self.value = value # 返回异常类对象的说明信息 def __str__(self): return "SignFailError:{} ".format(repr(self.value)) class LogFailError(Exception): """ 登录失败 """ # 自定义异常类型的初始化 def __init__(self, value): self.value = value # 返回异常类对象的说明信息 def __str__(self): return "LogFailError:{} ".format(repr(self.value)) class RegisteFailError(Exception): """ 注册失败 """ # 自定义异常类型的初始化 def __init__(self, value): self.value = value # 返回异常类对象的说明信息 def __str__(self): return "RegisteFailError:{} ".format(repr(self.value)) def main(): logging.debug("======start=%s======" % str(datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S"))) # 标志着调试开始 e = None a = 0 try: # ==================主代码============================= # a = 1/a # raise Exception("自定义异常抛出") # 自己抛出异常 可以自定义个异常类 也可以不用想太多直接用这个方式即可 raise SignFailError("签到失败") except ValueError as e: # 同时应对多种异常的写法 logging.debug("数字格式异常") logging.debug(repr(e)) # 返回普通的异常信息,包括异常信息的类型 # traceback.print_tb(sys.exc_info()[2]) logger.error(traceback.format_exc(limit=3)) # 输出更多的反馈信息 except ArithmeticError as e: # 同时应对多种异常的写法 logging.debug("算术异常") logging.debug(repr(e)) # 返回较全的异常信息,包括异常信息的类型 # logging.debug(str(traceback.print_tb(sys.exc_info()[2]))) logger.error(traceback.format_exc(limit=3)) # 输出更多的反馈信息 except SignFailError as e: # 同时应对多种异常的写法 # logging.debug("算术异常") logging.debug(repr(e)) # 返回较全的异常信息,包括异常信息的类型 # logging.debug(str(traceback.print_tb(sys.exc_info()[2]))) logger.error(traceback.format_exc(limit=3)) # 输出更多的反馈信息 except LogFailError as e: # 同时应对多种异常的写法 # logging.debug("算术异常") logging.debug(repr(e)) # 返回较全的异常信息,包括异常信息的类型 # logging.debug(str(traceback.print_tb(sys.exc_info()[2]))) logger.error(traceback.format_exc(limit=3)) # 输出更多的反馈信息 except RegisteFailError as e: # 同时应对多种异常的写法 # logging.debug("算术异常") logging.debug(repr(e)) # 返回较全的异常信息,包括异常信息的类型 # logging.debug(str(traceback.print_tb(sys.exc_info()[2]))) logger.error(traceback.format_exc(limit=3)) # 输出更多的反馈信息 except (ValueError, ArithmeticError): # 同时应对多种异常的写法 logging.debug("程序发生了数字格式异常、算术异常之一") except Exception as e: # Exception as e 放在else之前表示 如果上面都没找到错误应对 那么剩下的异常都归这里 # 输出错误信息 但是并没有太详细 更加详细复杂的错误反馈需要用到 traceback 模块 logging.debug(repr(e)) # 返回较全的异常信息,包括异常信息的类型 # traceback.print_tb(sys.exc_info()[2]) logger.error(traceback.format_exc(limit=3)) # 输出更多的反馈信息 else: logging.debug("无异常") # 没发生异常就跳转到这里 finally: logging.debug("不管有无异常都要执行这") # 不管有无异常都要执行这
手动抛出异常和常见用法
一般是用于让代码和异常处理分离 不过 我们也可以定义自己的异常类 来标识自己独有的异常 比如说 签到操作没有完成 但是代码没有错误 这个时候我们可以自定义一个异常类类型 然后自己命名这个异常类型的名字和提示的错误信息 发现签到操作没完成 就抛出一个SignFailError的自定义异常类型 在try except里面捕获这个自定义类型然后针对性的处理
异常信息的反馈提示
import traceback
import logging # 导入日志模块
logger = logging.getLogger("traceback_test") # 配合 traceback.format_exc 输出更详细的情况
logger.error(traceback.format_exc(limit=3)) # 输出更多的反馈信息
模块 包 库 函数 类
函数
类
模块
本质:模块 每个py文件都是一个模块 里面包含了变量 函数 类 等等
导入方式
1.import 模块名1 [as 别名1], 模块名2 [as 别名2],… 这种调用需要 模块1.方法1()
2.from 模块名 import 成员名1 [as 别名1],成员名2 [as 别名2],… 这种可以直接调用 成员名()
不推荐 form zjl import * 因为可能模块zjl里面有和当前页面重名的函数 变量 类 等等 因为这种方式调用不用加命名空间 无法和本地的变量区分开来
导入多个相同模块的问题
一个页面导入相同模块多次 或者 main页面 导入了一个aa的模块 但是 main模块中 还调用了工具模块 而工具模块中依然导入了aa的模块 会发生什么
编译器会智能识别 只会调用一次 所以我们无需担心 在main文件调用一批模块或者第三方库 然后由于有需要 还在自定义模块里面再次调用这些东西
导入模块的本质
实际上就是将整个模块载入到内存中先编译执行 然后将整个模块的内容赋值给和模块名同名的变量 该变量类型为module
自定义模块编写说明文档
在模块开头写上即可 在模块名上停留或者ctrl+q 就可以看到这些提示 提示该模块包含的变量 类 函数等等
'''
demo 模块中包含以下内容:
name 字符串变量:初始值为“Python教程”
add 字符串变量:初始值为“http://c.biancheng.net/python”
say() 函数
CLanguage类:包含 name 和 add 属性和 say() 方法。
'''
载入特殊的有空格的或者数字开头的模块
__import__("demo text")
找不到模块文件怎么办
查看模块路径(包也是一种特殊模块 一样可以查看)
print(my_module1.__file__)
我们可以使用这个属性 获取到绝对路径
比如假设某个模块肯定位于根目录下
my_package.__file__.split(”module1”)[0] 这样就获取到了目录的绝对路径
包
本质:本质就是个文件夹 也是一种特殊的模块 但是这个文件夹有个特殊的__init__.py文件来管理这个特殊文件夹的内容 包含多个模块
创建包
- file->new->python package 创建包
- 在包文件夹里面创建模块文件 写入模块内的代码
- 在__init__.py里面 增加包内模块文件的导入语句 把模块导入进包里面
from . import 模块名1 # 这里.就是指代当前包的包名
from . import 模块名2
导入方式
import 包名[.模块名 [as 别名]] 推荐
from 包名 import 模块名 [as 别名]
from 包名.模块名 import 成员名 [as 别名]
导入包的本质
其实就是执行了__init__.py 然后把执行结果赋值给了和包名同名的变量 等待进一步的调用
查看包结构
dir(包名或者类名)
库
库由多个包构成
模块开发原则和py文件的基本结构
1.每个py文件都可能随时变成模块 所以我们每个py文件里面都要引入main()函数 所有要执行的代码都扔进这个main()函数里面执行
2.使用__name__来判断当前页面是作为运行还是作为模块被调用 以此来决定是否执行本页面的main()
#!/usr/bin/env python3 # -*- coding: utf-8 -*- # author:albert time:2020/9/6 # import random # 导入random库 import datetime # 日期时间模块 # import zjl # import sys # import test_model as tm import traceback import logging # 导入日志模块 import test_pack logger = logging.getLogger("traceback_test") # 配合 traceback.format_exc 输出更详细的情况 # ========================================控制台==================================================== config_dict = dict() # 作者相关 config_dict["author"] = "zjl" config_dict["QQ"] = "1847154827" # 日志 config_dict["islog"] = 1 # 是否开启调试 config_dict["islogfile"] = 0 # 是否输出到日志文件 config_dict["logfilepath"] = "log_" + datetime.datetime.now().strftime("%Y-%m-%d") + ".txt" # ========================================配置函数==================================================== def config_fun(temp_config_dict): # 配置调试和日志 if temp_config_dict["islogfile"] == 1: logging.basicConfig(filename=temp_config_dict["logfilepath"], level=logging.DEBUG, format="%(asctime)s,%(msecs)d %(levelname)-8s [%(filename)s:%(lineno)d] %(message)s", datefmt="%d-%m-%Y:%H:%M:%S") else: logging.basicConfig(level=logging.DEBUG, format="%(asctime)s,%(msecs)d %(levelname)-8s [%(filename)s:%(lineno)d] %(message)s", datefmt="%d-%m-%Y:%H:%M:%S") if temp_config_dict["islog"] == 1: pass else: logging.disable(logging.DEBUG) # ========================================类函数区(或者放到一个模块里面)==================================================== class SignFailError(Exception): """ 签到失败 """ # 自定义异常类型的初始化 def __init__(self, value): self.value = value # 返回异常类对象的说明信息 def __str__(self): return "SignFailError:{} ".format(repr(self.value)) class LogFailError(Exception): """ 登录失败 """ # 自定义异常类型的初始化 def __init__(self, value): self.value = value # 返回异常类对象的说明信息 def __str__(self): return "LogFailError:{} ".format(repr(self.value)) class RegisteFailError(Exception): """ 注册失败 """ # 自定义异常类型的初始化 def __init__(self, value): self.value = value # 返回异常类对象的说明信息 def __str__(self): return "RegisteFailError:{} ".format(repr(self.value)) # ========================================本页主函数 配上异常处理部分======================================== def main(): logging.debug("======start=%s======" % str(datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S"))) # 标志着调试开始 e = None a = 0 try: # ==================主代码============================= # a = 1/a # raise Exception("自定义异常抛出") # 自己抛出异常 可以自定义个异常类 也可以不用想太多直接用这个方式即可 raise SignFailError("签到失败") except ValueError as e: # 同时应对多种异常的写法 logging.debug("数字格式异常") logging.debug(repr(e)) # 返回普通的异常信息,包括异常信息的类型 # traceback.print_tb(sys.exc_info()[2]) logger.error(traceback.format_exc(limit=3)) # 输出更多的反馈信息 except ArithmeticError as e: # 同时应对多种异常的写法 logging.debug("算术异常") logging.debug(repr(e)) # 返回较全的异常信息,包括异常信息的类型 # logging.debug(str(traceback.print_tb(sys.exc_info()[2]))) logger.error(traceback.format_exc(limit=3)) # 输出更多的反馈信息 except SignFailError as e: # 同时应对多种异常的写法 # logging.debug("算术异常") logging.debug(repr(e)) # 返回较全的异常信息,包括异常信息的类型 # logging.debug(str(traceback.print_tb(sys.exc_info()[2]))) logger.error(traceback.format_exc(limit=3)) # 输出更多的反馈信息 except LogFailError as e: # 同时应对多种异常的写法 # logging.debug("算术异常") logging.debug(repr(e)) # 返回较全的异常信息,包括异常信息的类型 # logging.debug(str(traceback.print_tb(sys.exc_info()[2]))) logger.error(traceback.format_exc(limit=3)) # 输出更多的反馈信息 except RegisteFailError as e: # 同时应对多种异常的写法 # logging.debug("算术异常") logging.debug(repr(e)) # 返回较全的异常信息,包括异常信息的类型 # logging.debug(str(traceback.print_tb(sys.exc_info()[2]))) logger.error(traceback.format_exc(limit=3)) # 输出更多的反馈信息 except (ValueError, ArithmeticError): # 同时应对多种异常的写法 logging.debug("程序发生了数字格式异常、算术异常之一") except Exception as e: # Exception as e 放在else之前表示 如果上面都没找到错误应对 那么剩下的异常都归这里 # 输出错误信息 但是并没有太详细 更加详细复杂的错误反馈需要用到 traceback 模块 logging.debug(repr(e)) # 返回较全的异常信息,包括异常信息的类型 # traceback.print_tb(sys.exc_info()[2]) logger.error(traceback.format_exc(limit=3)) # 输出更多的反馈信息 else: logging.debug("无异常") # 没发生异常就跳转到这里 finally: logging.debug("不管有无异常都要执行这") # 不管有无异常都要执行这 logging.debug("======end=%s======" % str(datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S"))) # 标志着调试结束 # 当前页面是入口文件才会执行main函数 被调用的时候不会执行 if __name__ == "__main__": config_fun(config_dict) main()
文件目录操作
创建文件文件夹
os.mkdir() 只能创建一层目录 无法递归创建
os.makedirs() 能递归创建目录 不会报错 推荐 但是如果目录已经存在了 两个函数都会报错 所以要配合os.path.exist() 使用
temp1_path = os.getcwd() +os.sep + "log" + os.sep + "a" if os.path.exists(temp1_path): # 目录存在不用创建 logging.debug("[%s] 已经存在" % temp1_path) else: # 目录不存在则创建 logging.debug(os.makedirs(temp1_path))
复制文件文件夹
shutil.copyfile("oldfile","newfile") # oldfile和newfile都只能是文件 操作前还是要判断下是否都是文件或者都是文件夹
移动文件文件夹
shutil.move("oldpos","newpos") # 操作前还是要判断下是否都是文件或者都是文件夹
重命名文件文件夹
os.renames(old, new) # 递归重命名 没什么说的
删除文件文件夹
删除目录 os.rmdir(path) os.removedirs(path)(两者都不推荐 如果文件夹不为空 则删除报错)
推荐 shutil.rmtree 删除目录 不管你空不空 都删除干净
删除文件 os.remove() 删除文件一样要先判断存在再删除 因为删除的文件不在 一样要报错
import shutil temp1_path = os.getcwd() +os.sep + "a" + os.sep + "bb" logging.debug(os.listdir(temp1_path)) if os.path.exists(temp1_path): # 目录存在要删除 shutil.rmtree(temp1_path) # logging.debug(os.removedirs(temp1_path)) logging.debug("[%s] 删除成功" % temp1_path) else: # 目录不存在 不用删除 logging.debug("[%s] 不存在不用删除" % temp1_path)
判断文件文件夹 是否存在 os.path.exists
logging.debug(os.path.exists('..\\python1')) # 可以判断文件 目录 支持相对路径和绝对路径 如果配合os.path.isfile os.path.isdir 可以进一步的判断是目录还是文件
def file_dir_exists(temp1_path): """ :param temp1_path: 要检测的路径 支持文件路径 目录路径 :return: -1 表示不存在 0 表示存在而且是文件 1 表示存在 是文件夹 :function: 是判断文件或者目录是否存在 :base: 需要os模块的支持 """ temp1_result = -1 if os.path.exists(temp1_path): if os.path.isfile(temp1_path): temp1_result = 0 elif os.path.isdir(temp1_path): temp1_result = 1 else: temp1_result = -1 else: temp1_result = -1 return temp1_result
遍历文件夹
logging.debug(os.listdir(os.getcwd())) # 返回一个包含当前目录下的所有文件文件夹的列表
路径拼接 os.path.join
logging.debug(os.getcwd()) # 取当前所在文件的目录绝对路径
logging.debug(os.path.abspath("test1.py")) # 相对转绝对地址1
logging.debug(os.path.abspath(".\\test1.py")) # 相对转绝对地址2
logging.debug(os.path.split(a)) 将路径转换为dirname 和basename两部分的元组 相对路径也可以拆分 但是感觉怪怪的
logging.debug(os.path.dirname(a))
logging.debug(os.path.basename(a))
logging.debug(os.sep) # 会根据当前系统情况来输出正确的路径斜线
logging.debug(os.path.join(os.path.dirname(a), os.path.basename(a))) # 利用前面提到的这些拼接成完整路径 E:\python\test1.py
logging.debug(os.path.join(os.getcwd(), “test1.py”)
Python的路径的斜线问题
众所周知 window下路径的斜线用\ 但是linux下的路径斜线用/ 而且在windows下手写路径写入\ 还要考虑转义字符问题\\->\ 那么我们平时Python的路径 应该怎么处理才能适应多个曹组系统
1.logging.debug(os.sep) # os.sep 会根据当前系统情况来输出正确的路径斜线
2.logging.debug(os.path.join(".", "python", "test1111.py")) # 把路径的部分拆开 然后用os.path.join拼接到一起 或者用os.path.dirname 或者os.getcwd() 提取出目录地址 然后用os.path.join拼接成一个完整路径
3 Python3.4+的os.path.pathlib模块
import pathlib # 导入pathlib
logging.debug(pathlib.Path("e:/python/test_pack/test_pack_module1.py")) # 以正斜线来描述路径 pathlib.Path会自动根据系统返回合适的路径
open()函数
file = open(file_name [, mode='r' [ , buffering=-1 [ , encoding = None ]]])
file_name:就是要打开了文件路径 为了以防万一还是要检测下该文件是否是文件 是否存在
mode:这个都明白 常见备选的有 r r+ w w+ a a+
buffering:就是对文件操作的时候 是否开启缓冲区 但是这个参数意义不大 因为如果我们写入文本文件的时候 缓冲区必须是打开的 不然会报错 开启缓冲区的作用只是让操作 比如写入操作不会立刻执行 而是等一系列操作后 遇到close() 的时候 从缓冲区读取系列操作 一次性执行完毕 如果没遇到close但是想立刻执行则 使用flush()来实现阶段性的执行
encoding:没什么说的 文本文件使用的编码格式
读取文件内容
- f = open("a.txt", 'r')
- temp1 = f.read()
- print(temp1)
- f.close()
写入原理
我们写入文本文件的时候 缓冲区必须是打开的 不然会报错 开启缓冲区的作用只是让操作 比如写入操作不会立刻执行 而是等一系列操作后 遇到close() 的时候 从缓冲区读取系列操作 一次性执行完毕 如果没遇到close但是想立刻执行则 使用flush()来实现阶段性的执行
写入文件内容
- f = open("a.txt", 'w')
- f.write("覆盖写入")
- f.close()
追加文件内容
- f = open("a.txt", 'a')
- f.write("追加写入")
- f.close()
读取文件指定行内容
- f = open("a.txt", 'r')
- temp1 = f.readline() # 读取一行内容
- print(temp1)
- f.close()
读取文件内容返回列表
- f = open('a.txt', 'r')
- n = open('b.txt','w+')
- n.writelines(f.readlines())
- n.close()
- f.close()
with as的使用 (推荐这个方式 会自动close 报错也会自动执行close)
with open(temp1_path, "r") as f:
logging.debug(f.read())
使用这种形式非常方便 就算代码内部出错了一样会自动close 推荐这个方式
日志调试信息
完整的日志调试代码
import logging # 导入日志模块 # =====配置调试信息======= 是否输出到文件 调试信息等级 信息格式等等 设置所在文件 设置行号 如果要变成日志输出到日志文件 则 # 日志文件:logging.basicConfig(filename='demo.txt', level=logging.DEBUG, format='%(asctime)s - %(levelname)s - %(message)s') logging.basicConfig(level=logging.DEBUG,
format="%(asctime)s,%(msecs)d %(levelname)-8s [%(filename)s:%(lineno)d] %(message)s",
datefmt="%d-%m-%Y:%H:%M:%S"
) """ logging.CRITICAL: 致命错误 最高等级 logging.ERROR: 用于记录错误,它导致程序做某事失败 logging.WARNING:用于表示可能的问题,它不会阻止程序的工作,但将来可能会。 logging.INFO:用于记录程序中一般事件的信息,或确认一切工作正常 logging.DEBUG:最低级别,用于小细节,通常只有在诊断问题时,才会关心这些消息 logging.disable 会把参数的错误等级和该参数下面的错误等级一起关闭 这些错误都不会出现在调试信息里面 """ # logging.disable(logging.DEBUG) # 控制调试信息的显示等级 控制是否显示调试信息 logging.debug("======start=======") # 标志着调试开始 # logging.debug支持print的字符串格式化 aa = 100 logging.debug("======start=====%d==" % aa) for i in range(10): logging.debug('i: ' + str(i)) # 正常的调试信息 logging.debug("======end=======") # 标志着调试结束
logging的强大功能 似乎print也被完全代替了 之后代码都采用logging来反馈信息
结果
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!