背景
1、os和sys能够帮助我们切换路径,管理整体项目文档,找到对应的代码和需要的数据。
2、使用logging实现在项目运行的过程当中对关键节点内容的记录
针对问题1
os模块基本操作
import os
# 当前目录
current_directory = os.getcwd()
print("当前目录:", current_directory)
# 上级目录
parent_directory = os.path.dirname(current_directory)
print("上级目录:", parent_directory)
# 目录拼接
# 假设我们要创建一个子目录
sub_directory = 'new_sub_directory'
# 拼接当前目录与子目录
full_path = os.path.join(current_directory, sub_directory)
print("目录拼接:", full_path)
# 创建这个子目录
os.makedirs(full_path, exist_ok=True)
更新1,找到项目的根目录位置:
import os
def find_project_root(start_path):
original_path = start_path
while start_path:
# 检查当前路径是否包含项目根目录的标识,例如'.git'文件夹或特定配置文件
if os.path.exists(os.path.join(start_path, '.git')) or \
os.path.exists(os.path.join(start_path, 'requirements.txt')) or \
os.path.exists(os.path.join(start_path, 'setup.py')):
return start_path
# 向上移动到父目录
start_path = os.path.dirname(start_path)
raise FileNotFoundError("Project root directory not found, starting from: " + original_path)
# 使用 __file__ 来获取当前文件的路径
current_file_path = os.path.abspath(__file__)
# 尝试找到项目根目录
try:
project_root = find_project_root(os.path.dirname(current_file_path))
print("项目根目录:", project_root)
except FileNotFoundError as e:
print(e)
其实我们找到这些目录的作用有两个:
1、实现路径控制,获取配置文件、本地数据、以及持久化。
2、实现项目框架的控制,将路径添加到sys当中,方便找到对应的代码功能模块。
print(os.getcwd()) #获取当前目录的绝对路径
print(os.listdir()) #列出当前目录下的文件文件夹名,返回一个列表并打印
#打印列表中的每个值
for item in os.listdir():
print(item)
print(os.path.abspath(__file__)) #获取当前脚本文件的绝对位置并打印
print(os.path.dirname(__file__))
#注意,os.path.dirname()输出的脚本所在目录绝对路径的斜杠是正的。正斜杠(forward slash'/'),反斜杠(back slash'\')。Windows系统中文件路径为反斜杠,如D:\16.test\DLC
#os.path.join():连接路径
path = os.getcwd()
config_path = os.path.join(path, "searching2-searching2-2020-11-27", "config.yaml")
#注意:os.path.join()连接出来路径带反斜杠。
#检测文件或文件夹是否存在
print(os.path.exists(config_path))
print(os.path.exists(os.getcwd()))
sys模块基本操作
sys 模块提供了很多底层操作,可以对 Python 解释器的行为进行控制和定制。在使用时,需要谨慎,以避免不期望的行为。
优雅地退出程序:
import sys
def exit_gracefully():
print("程序正在退出...")
sys.exit(0) # 正常退出,返回状态码0
exit_gracefully()
动态添加模块搜索路径:
import sys
custom_path = '/path/to/custom/module'
if custom_path not in sys.path:
sys.path.append(custom_path)
print("已添加自定义路径到模块搜索路径:", sys.path)
捕获和打印未捕获的异常:
import sys
try:
# 这里故意抛出一个异常
raise ValueError("这是一个测试异常")
except ValueError as e:
print("捕获到 ValueError:", e)
finally:
# 打印异常信息到标准错误
print("程序执行完毕,无论是否发生异常。", file=sys.stderr)
使用标准输入输出:
import sys
# 打印欢迎信息到标准输出
print("请输入你的名字:", file=sys.stdout)
# 从标准输入读取一行文本
name = input()
print("你好,", name, file=sys.stdout)
设置递归深度限制:
import sys
print("当前递归深度限制:", sys.getrecursionlimit())
sys.setrecursionlimit(3000) # 设置新的递归深度限制
print("新的递归深度限制:", sys.getrecursionlimit())
执行动态语句:
import sys
# 动态地定义一个变量
sys.modules[__name__].__dict__['dynamic_var'] = 42
print("动态变量的值:", dynamic_var)
获取环境变量:
import os
# 使用 os 模块获取环境变量
user_home = os.getenv('HOME')
print("用户主目录:", user_home)
应用
Q:自定义的包为什么不能被程序代码找到?
在定义了__init__.py文件之后,将自定义的包添加到启动导入当中,为什么不能能够在测试当中被发现?因为测试的运行方式必须也使用cmd行的方式进行启动,只有这样才会运行。
在 Python 中,当你在一个包的 init.py 文件中定义函数时,这些函数通常被视为包级别的函数。这意味着,要使用这些函数,你需要从包中导入它们,而不是直接引用函数名。
你提供的 init.py 文件中的 initialize_sys_path 函数,应该通过以下方式导入和使用:
from your_package import initialize_sys_path
initialize_sys_path()
这里的 your_package 是包含 init.py 的包的名称。如果你的包结构如下所示:
your_project/
│
├── your_package/
│ ├── __init__.py
│ ├── some_module.py
│ └── ...
│
└── some_script.py
在 some_script.py 中,如果你想调用 initialize_sys_path 函数,你应该这样做:
from your_package import initialize_sys_path
initialize_sys_path()
如果你在 some_module.py 中调用这个函数,你应该这样做:
from . import initialize_sys_path # 使用相对导入
initialize_sys_path()
请注意以下几点:
确保 init.py 中的 initialize_sys_path 函数没有被定义为私有函数(即不要使用下划线 _ 前缀)。
如果你尝试从同级的 .py 文件中直接调用 initialize_sys_path 函数,而没有通过 import 导入它,Python 解释器将无法识别这个函数。
如果你正在使用相对导入(例如 from . import initialize_sys_path),确保你的脚本被当作包的一部分来执行,而不是作为主程序。这意味着你不能使用 -m 参数或直接运行脚本,因为这样 Python 解释器不会将脚本视为包的一部分。
如果你遵循了上述步骤,但仍然无法引用 initialize_sys_path 函数,请检查以下几点:
确保你的包结构正确,init.py 文件存在于包目录中。
确保你没有在函数名前使用下划线 _,这将使函数成为私有的。
确保你的导入语句正确无误,并且包名与实际的包名匹配。
如果你的脚本是作为主程序运行的,尝试将其作为模块来运行,例如使用 python -m your_package.some_module。
针对问题2:
logging模块基本操作
logging 是 Python 的一个标准库模块,用于记录程序运行时的信息。下面是一些基本操作:
import logging
# 设置日志级别:日志级别从低到高分为:DEBUG, INFO, WARNING, ERROR, CRITICAL。
logging.basicConfig(level=logging.DEBUG)
logger = logging.getLogger('my_logger') # 创建日志记录器:可以创建一个日志记录器,用于记录日志。
#记录日志:使用日志记录器记录不同级别的日志。
logger.debug('This is a debug message')
logger.info('This is an info message')
logger.warning('This is a warning message')
logger.error('This is an error message')
logger.critical('This is a critical message')
# 设置日志格式:可以设置日志的输出格式。
logging.basicConfig(format='%(asctime)s - %(name)s - %(levelname)s - %(message)s')
# 设置日志文件:可以将日志输出到文件。
logging.basicConfig(filename='app.log', filemode='w', level=logging.INFO)
# 设置日志旋转:可以使用 RotatingFileHandler 来实现日志文件的自动旋转。
from logging.handlers import RotatingFileHandler
handler = RotatingFileHandler('app.log', maxBytes=1024, backupCount=5)
logger.addHandler(handler)
#设置日志过滤:可以设置过滤器来控制日志的输出。
class MyFilter(logging.Filter):
def filter(self, record):
return record.levelno == logging.ERROR
logger.addFilter(MyFilter())
# 设置日志处理器:除了 RotatingFileHandler,还有 StreamHandler, FileHandler 等处理器。
console_handler = logging.StreamHandler()
logger.addHandler(console_handler)
#配置日志:可以使用 config 模块来配置日志。
import logging.config
logging.config.fileConfig('logging.conf')
这些是 logging 模块的一些基本操作。根据需要,可以进行更复杂的配置和使用。