worknote
python知识笔记
一、Magic Method
1.Magic Method 是一个以双下划线开始和结尾的方法。它们由 Python 中的内置类定义,通常用于运算符重载。(重载是指在同一个类中,可以定义多个同名的方法,但这些方法的参数类型、参数个数或返回值类型不同。重载的作用是可以根据不同的参数类型或参数个数来执行不同的操作,提高代码的灵活性和可读性。)
2.
__name__
与__call__
1.
__name__
:由于Python中没有 main()函数,因此当向解释器发出运行 python 程序的命令时,将执行级别为 0 缩进的代码。但是,在此之前,它将定义一些特殊变量。__name__
就是这样一个特殊的变量。如果源文件作为主程序执行,则解释器将__name__
变量设置为值为“__main__
”。如果从另一个模块导入此文件,__name__
将设置为该模块的名称。
__name__
是一个内置变量,其计算结果为当前模块的名称。因此,它可用于检查当前脚本是单独运行还是通过将其与 if 语句组合到其他地方来导入,如if __name__ == '__main__'
。例:
# File1.py print ("File1 __name__ = %s" %__name__) if __name__ == "__main__": print ("File1 is being run directly") else: print ("File1 is being imported") # File2.py import File1 print ("File2 __name__ = %s" %__name__) if __name__ == "__main__": print ("File2 is being run directly") else: print ("File2 is being imported") Now the interpreter is given the command to run File1.py. python File1.py Output : File1 __name__ = __main__ File1 is being run directly And then File2.py is run. python File2.py Output : File1 __name__ = File1 File1 is being imported File2 __name__ = __main__ File2 is being run directly
如上所示,当直接运行File1.py时,解释器将
__name__
变量设置为__main__
,当它通过导入File2.py运行时,__name__
变量被设置为python脚本的名称,即File1。因此,可以说,如果__name__ == “__main__”
是使用python File1.py等命令从命令行运行脚本时运行的程序部分。2.
__call__
:创建一个可调用的实例,也可以理解为是把对象当成函数来使用的时候,会自动调用。例:
class test(): def __call__(self, a, b): print("__call__() is being called") print(a + b) t = test() t(2, 2) print("*" * 20) t.__call__(2, 2) Output: __call__() is being called 4 ******************** __call__() is being called 4
3.
if __name__ == '__main__':
含义1.简而言之允许您在文件作为脚本运行时执行代码,但在将其作为模块导入时不执行代码
二、logging
1.logging内置函数和各个级别划分
你想要执行的任务 此任务最好的工具 对于命令行或程序的应用,结果显示在控制台。 print() 在对程序的普通操作发生时提交事件报告(比如:状态监控和错误调查) logging.info() 函数(当有诊断目的需要详细输出信息时使用 logging.debug()函数) 提出一个警告信息基于一个特殊的运行时事件 warnings.warn() 位于代码库中,该事件是可以避免的,需要修改客户端应用以消除告警logging.warning()不需要修改客户端应用,但是该事件还是需要引起关注 对一个特殊的运行时事件报告错误 引发异常 报告错误而不引发异常(如在长时间运行中的服务端进程的错误处理) logging.error(), logging.exception() 或 logging.critical()分别适用于特定的错误及应用领域 日志功能应以所追踪事件级别或严重性而定。各级别适用性如下(以严重性递增):
级别 何时使用 DEBUG
细节信息,仅当诊断问题时适用。 INFO
确认程序按预期运行。 WARNING
表明有已经或即将发生的意外(例如:磁盘空间不足)。程序仍按预期进行。 ERROR
由于严重的问题,程序的某些功能已经不能正常执行 CRITICAL
严重的错误,表明程序已不能继续执行 默认的级别是
WARNING
,意味着只会追踪该级别及以上的事件,除非更改日志配置。例如:
printin import logging logging.warning('Watch out!') # will print a message to the console logging.info('I told you so') # will not print anything printout WARNING:root:Watch out!
2.记录日志到文件
设置日志追踪级别的阈值
printin: import logging logging.basicConfig(filename='example.log', encoding='utf-8', level=logging.DEBUG) logging.debug('This message should go to the log file') logging.info('So should this') logging.warning('And this, too') logging.error('And non-ASCII stuff, too, like Øresund and Malmö') printout: DEBUG:root:This message should go to the log file INFO:root:So should this WARNING:root:And this, too ERROR:root:And non-ASCII stuff, too, like Øresund and Malmö
从命令行设置日志级别,例如:
--log=INFO 将 --log 命令的参数存进了变量 loglevel 或者 getattr(logging, loglevel.upper()) numeric_level = getattr(logging, loglevel.upper(), None)d
3.从多个模块记录日志
如果你的程序包含多个模块,这里有一个如何组织日志记录的示例:
# myapp.py import logging import mylib def main(): logging.basicConfig(filename='myapp.log', level=logging.INFO) logging.info('Started') mylib.do_something() logging.info('Finished') if __name__ == '__main__': main()
# mylib.py import logging def do_something(): logging.info('Doing something')
4.记录变量数据
printin: import logging logging.warning('%s before you %s', 'Look', 'leap!') printout: WARNING:root:Look before you leap!
5.更改显示消息
printin: import logging logging.basicConfig(format='%(levelname)s:%(message)s', level=logging.DEBUG) logging.debug('This message should appear on the console') logging.info('So should this') logging.warning('And this, too') printout: DEBUG:This message should appear on the console INFO:So should this WARNING:And this, too
注意format格式 format=‘%(name)s’
6.在消息中显示日期/时间
printin: import logging logging.basicConfig(format='%(asctime)s %(message)s', datefmt='%m/%d/%Y %I:%M:%S %p') logging.warning('is when this event was logged.') printout: 不加datefmt:2010-12-12 11:41:42,612 is when this event was logged. 加datefmt:12/12/2010 11:46:36 AM is when this event was logged.
7.日志组件
日志库采用模块化方法,并提供几类组件:记录器、处理器、过滤器和格式器。
- 记录器暴露了应用程序代码直接使用的接口。
- 处理器将日志记录(由记录器创建)发送到适当的目标。
- 过滤器提供了更细粒度的功能,用于确定要输出的日志记录。
- 格式器指定最终输出中日志记录的样式。
8.日志文件大概模板
1.创建日志记录器对象。 2.设置日志文件路径,确保目录存在。 3.创建 TimedRotatingFileHandler 处理器,用于按日期轮转日志文件,并保留一定数量的旧日志文件。 4.设置日志格式。 5.设置日志记录器的日志级别。 6.将处理器添加到日志记录器。 def setup_logging(): ## 第一步:创建logger对象 logger = logging.getLogger() ## 第二步:设置logs路径 project_root = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) log_file_dir = os.path.join(project_root, "logs") os.makedirs(log_file_dir, exist_ok=True) log_file_path = os.path.join(log_file_dir, "log_file.log") ## 第三步:设置轮转周期为1天,保留3份日志文件 handler = TimedRotatingFileHandler( log_file_path, when="D", interval=1, backupCount=3 ) ## 第四步:设置日志格式、等级 log_format = "%(asctime)s - %(levelname)s - %(message)s" handler.setFormatter(logging.Formatter(log_format)) logger.setLevel(logging.DEBUG) ## 第五步:添加到日志记录器 logger.addHandler(handler) return logger logger = setup_logging()
9.TimedRotatingFileHandler
TimedRotatingFileHandler
是 Python 中logging.handlers
模块提供的一个处理器,用于按照一定的时间间隔轮转日志文件。它允许你在一定时间内(如每天、每小时)自动创建新的日志文件,以便保留旧日志文件并方便日志的管理。用法:
from logging.handlers import TimedRotatingFileHandler handler = TimedRotatingFileHandler(filename, when="midnight", interval=1, backupCount=3)
filename
: 指定日志文件的路径和名称。when
: 指定轮转的时间单位。可选值包括"midnight"
、"W0"
到"W6"
(星期一到星期日)、"D"
(天)、"H"
(小时),具体取决于你希望的轮转单位。interval
: 指定轮转的时间间隔。例如,如果when="midnight"
,interval=1
,那么每天会创建一个新的日志文件。backupCount
: 指定保留的旧日志文件数量,超过这个数量的旧文件将被删除。例如:
handler = TimedRotatingFileHandler( log_file_path, when="D", interval=1, backupCount=3 )
10.多进程日志文件(multiprocessing_logging模块,多进程下导入一个logger日志文件)
import multiprocessing_logging .... .... logger = setup_logging() multiprocessing_logging.install_mp_handler()
三、钩子函数和装饰器区别
钩子函数(Hook Function)和装饰器(Decorator)都是在软件开发中用于扩展或修改功能的概念,但它们有不同的用途和实现方式。
钩子函数:
- 定义: 钩子函数是在特定事件或条件发生时执行的函数。这些函数通常是在程序中的特定点被调用,以允许用户自定义或扩展程序的行为。
- 用途: 钩子函数的目的是让用户或开发者能够在核心功能之外插入自定义代码,以实现特定的业务逻辑。
- 例子: 在事件驱动的框架或库中,回调函数通常充当钩子函数,例如,监听某个按钮的点击事件。
装饰器:
- 定义: 装饰器是一种特殊类型的函数,它可以用于修改其他函数的行为。装饰器本身接受一个函数作为输入,并返回一个新的函数,通常在返回的函数中包装了一些额外的功能。
- 用途: 装饰器通常用于代码重用、增加功能或修改函数的行为。它可以将横切关注点(cross-cutting concerns)如日志记录、性能测量、权限控制等与核心逻辑分离。
- 例子: 在 Flask 中,
@app.route
是一种装饰器,用于将路由函数绑定到特定的 URL。区别:
- 执行时机: 钩子函数是在特定事件或条件发生时主动被调用的,而装饰器是在函数定义时就被应用,可以看作是静态的。
- 用途: 钩子函数用于提供可扩展性,允许用户在程序的关键点插入自定义代码;装饰器用于修改或增加函数的行为,提高代码的可重用性和模块化。
- 语法: 钩子函数的语法取决于具体的框架或库,而装饰器在 Python 中是通过
@decorator
这样的语法糖来使用的。总的来说,虽然钩子函数和装饰器都是为了实现可扩展性和可重用性而设计的,但它们的应用场景和使用方式有所不同。
四、单元测试
1.单元测试注意事项:在用pytest进行单元测试时,需注意必须在tests文件下以test开头的pyt文件中的以test开头的方法下执行。例如:
然后在终端执行pytest进行单元测试
也可以用执行脚本方式进行单元测试
if __name__ == "__main__": test_get_wether_data_with_fake_lonOrlat()
五、路径问题
1.os.path.abspath(__file__) abspath()方法取得是绝对路径,__file__是 python的内置变量,作用是取当前文件的绝对路径或者相对路径,这样我们就得到了当前文件的绝对路径。 2.os.path.dirname() dirname()方法取得是当前路径的父级路径,即上一层路径。 3.os.path.join()路径拼接 例如:log_file_dir = os.path.join(project_root, "logs"),在项目路径下生成logs文件夹 例二:log_file_dir = os.path.join(project_root, "logs") log_file_path = os.path.join(log_file_dir, "log_file.log") 这种写法等同于log_file_path = os.path.join(project_root,"logs","log_file.log") 意思都是在项目路径下生成logs文件并在logs文件下生成log_file.log 4.对于os.makedirs(log_file_dir, exist_ok=True)中的exist_ok参数 如果目录已存在,由于 exist_ok 设置为 True,不会引发异常,而是默默地忽略。 例如:os.makedirs(os.path.join(project_root, "logs"), exist_ok=True) 如果project_root下没有logs文件则创建,如果有不会引发异常,默认忽略。
六、函数签名
1.函数签名就是包含参数函数名返回值类型
例如:
from typing import Tuple, List, Optional import pandas as pd def get_weather_data( point: Tuple, elements: List[str], url: str ) -> Optional[pd.DataFrame]:
参数:point(元组) elements(列表) url(str)
返回值类型:DataFrame
optional[x]如果X不存在,则函数会隐式返回
None
七、python所有错误类型
- SyntaxError(语法错误):当代码违反了Python语法规则时引发的错误。例如,缺少冒号或括号不匹配等。
- IndentationError(缩进错误):当代码块的缩进不正确时引发的错误。Python依赖于缩进来确定代码块的范围,因此缩进错误会导致代码无法正确解析。
- NameError(名称错误):当尝试访问未定义的变量或函数时引发的错误。通常是因为变量或函数名称拼写错误或未定义。
- TypeError(类型错误):当操作或函数应用于不兼容的数据类型时引发的错误。例如,尝试将整数和字符串相加会引发类型错误。
- IndexError(索引错误):当尝试访问序列(如列表或字符串)中不存在的索引时引发的错误。
- KeyError(键错误):当尝试使用字典中不存在的键访问字典时引发的错误。
- ValueError(值错误):当函数收到了正确类型的参数,但参数的值不合法时引发的错误。
- AttributeError(属性错误):当尝试访问对象不存在的属性时引发的错误。
- FileNotFoundError(文件未找到错误):当尝试打开不存在的文件时引发的错误。
- ImportError(导入错误):当导入模块时出现问题时引发的错误,可能是因为模块不存在或无法导入。
- IOError(输入/输出错误):在进行输入/输出操作时出现的错误。通常表示文件操作时的问题,如文件不存在、权限不足等。
- RuntimeError(运行时错误):在代码执行期间引发的错误,不属于其他特定类型的错误。通常表示程序运行时出现的问题,如递归深度超出限制等。
- ZeroDivisionError(除零错误):当尝试除以零时引发的错误。
- AssertionError(断言错误):当assert语句的条件为假时引发的错误。
- KeyboardInterrupt(键盘中断):当用户按下Ctrl+C中断程序执行时引发的错误。
- OverflowError(溢出错误):在算术运算中结果太大而无法表示时引发的错误。
- MemoryError(内存错误):当程序尝试使用超出可用内存范围的内存时引发的错误。
- RecursionError(递归错误):当递归调用的层数超过Python解释器的限制时引发的错误。
- StopIteration(停止迭代错误):当迭代器没有更多的值时引发的错误。
- TypeError(类型错误):当对象的类型不符合操作时引发的错误。
八、os、sys、re、math、datatime。
- os (操作系统接口):
- 模块提供了与操作系统交互的功能,包括文件和目录操作、进程管理、环境变量等。
- 可以用于创建、删除、移动文件和目录,执行系统命令,获取系统信息等。
- sys (系统特定参数及函数):
- 提供了访问Python解释器的功能和系统相关的变量和函数。
- 可以用于修改Python解释器的行为、获取命令行参数、处理异常等。
- re (正则表达式):
- 提供了处理正则表达式的功能,用于匹配、搜索和替换字符串中的文本模式。
- 可以用于文本处理、数据提取、模式匹配等。
- math (数学函数):
- 包含了许多数学函数,如三角函数、指数函数、对数函数、常数等。
- 可以用于进行数学计算、数据分析、科学计算等。
- datetime (日期和时间):
- 提供了处理日期和时间的功能,包括日期和时间的创建、格式化、计算等。
- 可以用于处理时间序列数据、日期计算、时区转换等。
九、函数特点以及五种函数调用方式
例如函数:
def add_numbers(a,b):
return a+b
一、函数特点:
- 接受参数:函数可以接受零个或多个参数,这些参数可以是必需的,也可以是可选的。
- 执行操作:函数可以执行特定的操作,如计算、处理数据、打印输出等。
- 返回结果:函数可以返回一个值,也可以返回多个值,用于将结果传递给调用者。
二、函数调用方式:
1.位置参数调用:按照函数定义时参数的顺序传递参数。
add_numbers(3,5)
2.关键字参数调用:通过参数名指定参数的值,顺序可以任意。
add_numbers(b=5, a=3)
3.混合位置参数和关键字参数调用:结合使用位置参数和关键字参数。
add_numbers(3, b=5)
4.默认参数调用:在函数定义时为参数提供默认值,在调用时可以不传递该参数。
def xx(name="world")
return f'Hello, {name}!'
result = xx()
5.可变数量的位置参数调用:使用
*args
表示可变数量的位置参数,允许传递任意数量的参数。
def sum_numbers(*args):
return sum(args)
result = sum_numbers(1, 2, 3, 4, 5)
6.可变数量的关键字参数调用:使用
**kwargs
表示可变数量的关键字参数,允许传递任意数量的关键字参数。
def display_info(**kwargs):
for key, value in kwargs.items():
print(f"{key}: {value}")
display_info(name="Alice", age=25, city="New York")
问题笔记
一、网络号变更重新连接问题
问题原因:连接SSH时格式不对
解决方案:1.正确格式为:ssh 用户名@网络号 (端口号默认22)
若有指定端口号则格式为 ssh 用户名@网络号 -p 端口号
2.注意用户名:虚拟机上是wcx@localhost 登录root后是root@localhost
示例:ssh wcx@192.168.233.129
二、多个视图函数使用相同的端点名报错问题
报错信息:View function mapping is overwriting an existing endpoint function
问题原因:当在 Flask 应用中使用装饰器时,确保装饰器返回的函数(通常是一个包裹原始视图函数的函数)具有唯一的端点名。Flask 默认使用函数名称作为端点名,如果多个视图函数使用相同的端点名,就会导致该错误。
解决方案:在我的代码中,问题出现在
exception_handler
装饰器返回的wrapper
函数上,默认的端点名可能导致冲突。解决方法是在每个使用该装饰器的视图函数上,使用@bp.route
装饰器时显式地设置endpoint
参数,以确保每个视图函数都有唯一的端点名。通过为每个视图函数设置独特的端点名解决该错误。示例:
@bp.route("/all", methods=["POST", "GET"], endpoint="post_all") @login_required @exception_handler def all(): # ... (原有的视图函数逻辑)
操作笔记
一、代码调试
1.vscode中运行和调试功能
tips:选择断点、选择解释器
2.pdb 侵入式方法
import pdb;pdb.set_trace() 放在代码中,命令行出现(pdb)表示正常打开
命令 解释 break 或 b 设置断点 continue 或 c 继续执行程序 list 或 l 查看当前行的代码段 step 或 s 进入函数(进入 for 循环用 next 而不是用 step) return 或 r 执行代码直到从当前函数返回 next 或 n 执行下一行 up 或 u 返回到上个调用点(不是上一行) p x 打印变量x的值 exit 或 q 中止调试,退出程序
二、代码格式化
# enter your virtul env
>>> conda activate <your env name>
# install library
>>> pip install black
# format code with black
>>> black <path to your py file>
# or format your whole project
>>> cd <path to your project>
>>> black .
三、git 操作时用OAuth2方式生成token令牌免密登录
1.生成令牌:点击preferences找到accessTokens
![外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传](https://img-home.csdnimg.cn/images/20230724024159.png?origin_url=C%3A%5CUsers%5CPC%5CAppData%5CRoaming%5CTy
pora%5Ctypora-user-images%5Cimage-20240131103119584.png&pos_id=img-UNNvvkNX-1719891207154)![外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传](https://img-home.csdnimg.cn/images/20230724024159.png?
origin_url=C%3A%5CUsers%5CPC%5CAppData%5CRoaming%5CTypora%5Ctypora-user-images%5Cimage-20240131103132151.png&pos_id=img-aPvKdEbX-1719891207155)2.用OAuth2方式登录
git clone http://oauth2:glpat-1iNFxq_wPkFqtVyE7PxS@10.142.7.99:32000/gloud-team/data-transfer.git
四、宿主机连接到虚拟机(VSCODE)
1.在虚拟机查看inet
ifconfig
命令找到inet2.在宿主机上终端查看能否ping到虚拟机
ping [网络号]
3.搜索栏中ctrl+shift+p 进行连接
>[inet]
4.连接后选择虚拟环境
select interpreter
五、git地址变化后操作:
1.地址变换后需要将远程的origin仓库清空
git remote -v
git remote remove origin
2.清空后再次添加origin远程仓库
git remote add origin http://oauth2:glpat-sk-sqsz3ndgZeafk_JyG@10.129.18.10:32000/gold-team/imlfap i.git
3.再与本地分支创建关联
git branch --set-upstream-to=origin/huaneng_dev huaneng_dev
分支 huaneng_dev 设置为跟踪来自 origin 的远程分支 huaneng_dev。
六、git dev合并到main后操作
1.先保存当前改动的代码,切到main分支并确保拉到的代码是最新的
git stash; git checkout main ;git pull origin main
2.删除本地dev分支,并重新创建并切换到dev分支
git branch -d dev;git checkout -b dev
3.推送新创建的
dev
分支到远程仓库,pop暂存代码
git push origin dev;git stash pop
代码结构
一、目录结构(project目录下)
1.logs文件(存放生成的logs日志文件)
2.settings(环境配置)
1.
__init__.py
初始env变量2.
common.py
存放公共的数据如:api_key\DB_name等3.
local.py
本地4.
production.py
生产5.
test.py
测试
3.src(源码文件)
1.utils文件(存放写着比较常用的函数py文件如data_check.py)
2.main.py(主代码)
3.logger.py(配置日志)
4.errors.py(自定义异常错误)
5.constants.py(用于存放源代码中主要的常变量)
GOLDWIND_PUBLIC_WEATHER_API = "https://weather-api.goldwind.com/forecast/atmos/elements" GOLDWIND_PRIVATE_WEATHER_API = "" MIN_LON = 73 MAX_LON = 136 MIN_LAT = 5 MAX_LAT = 54 PROJECT_ROOT = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
6.tests(用于单元测试)
7.
.dockerignore
这个文件告诉 Docker 构建上下文,哪些文件不应该被包含到最终的镜像中8.
.gitignore
用来指定 Git 版本
控制系统忽略哪些文件或目录的配置文件https://www.toptal.com/developers/gitignore
9.config.py(存放配置信息)
10.Dockerfile
11.jenkinsfile
12.requirments.txt