Python工程实践:从项目结构到异常处理的8个关键建议
本文总结了提升Python代码质量与可维护性的8个核心建议。涵盖项目目录规范、数据备份策略、相对路径配置、进度条工具tqdm的使用,以及利用PySnooper进行调试和通过上下文管理器优化异常处理逻辑。
1. 规范项目文件归档与目录结构
良好的项目结构是代码可维护性的基础。建议将项目文件预先进行归档,明确区分代码、数据与文档。具体操作如下:
- 将
Code、Data和文档分别置于不同的子文件夹中。 - 源代码文件应放置在主文件夹内。
- 脚本位于主目录,资源文件(如数据)应位于其同级或下级目录。
2. 严格保护源数据与备份策略
在数据处理流程中,永远不要手动修改源数据。为确保数据可回溯,必须对源数据做好备份。同时,代码及其他配置文件也应定期备份。推荐的工具包括:
- Git:用于代码版本控制。
- Rsync:用于高效文件备份。
- Dropbox或 Time Machine:用于云存储或本地系统备份。
3. 使用相对路径配置
硬编码绝对路径会降低代码的移植性。建议使用相对路径来配置文件访问,例如:./data/processed/test1.csv。此外,建议配置全局路径变量以统一管理资源位置。
示例代码如下:
# 设置主目录
HOME_PATH = r'E:\ML\190615- PROJECT1'
# 读取数据
data = open(HOME_PATH+'/data/processed/test1.csv')
data = pd.read_csv(data)
data.head()4. 提升代码可读性与执行反馈
在代码必要处做好备注与说明。对于耗时较长的循环操作,推荐使用 tqdm 库来显示进度条,提升用户体验。安装方式如下:
pip install tqdm5. 利用 PySnooper 进行异常定位
当遇到难以追踪的 Bug 时,PySnooper 是一个强大的调试工具。它是一个装饰器,可以将函数执行的每一步输出保存到日志文件(如 file.log)中。项目地址为 github.com/cool-RR/pysnooper。
使用示例:
import pysnooper
@pysnooper.snoop('./log/file.log')
def number_to_bits(number):
if number:
bits = []
while number:
number, remainder = divmod(number, 2)
bits.insert(0, remainder)
return bits
else:
return [0]
number_to_bits(6)6. 增强代码健壮性:异常处理
代码必须能够抵挡各种异常场景测试。异常处理由捕获和抛出两部分组成:
- 使用
try...except包裹特定语句以完成错误处理。 - 恰当使用
raise主动抛出异常。 - 需明确传入参数的类型和个数,例如:
def add(a, b):
if isinstance(a, int) and isinstance(b, int):
return a+b
else:
return '参数类型错误'
print(add(1, 2))
print(add(1, 'a'))7. 精准捕获异常,避免模糊处理
只做最精准的异常捕获,避免使用模糊的 Exception 捕获所有异常,以免吞噬 AttributeError 等本应抛出的异常。例如,在获取网页标题时,正则表达式操作本身不应抛出异常,若出现错误应通过 AttributeError 暴露:
示例代码:
from requests.exceptions import RequestException
def save_website_title(url, filename):
try:
resp = requests.get(url)
except RequestException as e:
print(f'save failed: unable to get page content: {e}')
return False
# 这段正则操作本身就是不应该抛出异常的,所以我们没必要使用 try 语句块
# 假如 group 被误打成了 grop 也没关系,程序马上就会通过 AttributeError 来
# 告诉我们。
obj = re.search(r'<title>(.*)</title>', resp.text)
if not obj:
print('save failed: title tag not found in page content')
return False
title = obj.group(1)
try:
with open(filename, 'w') as fp:
fp.write(title)
except IOError as e:
print(f'save failed: unable to write to file {filename}: {e}')
return False
else:
return True8. 利用上下文管理器简化异常逻辑
上下文管理器可以在退出时判断并替换异常,从而简化重复的异常处理逻辑。通过自定义上下文管理器,可以将底层异常转换为更具业务意义的异常。
示例实现:
class raise_api_error:
"""captures specified exception and raise ApiErrorCode instead
:raises: AttributeError if code_name is not valid
"""
def __init__(self, captures, code_name):
self.captures = captures
self.code = getattr(error_codes, code_name)
def __enter__(self):
# 该方法将在进入上下文时调用
return self
def __exit__(self, exc_type, exc_val, exc_tb):
# 该方法将在退出上下文时调用
# exc_type, exc_val, exc_tb 分别表示该上下文内抛出的
# 异常类型、异常值、错误栈
if exc_type is None:
return False
if exc_type == self.captures:
raise self.code from exc_val
return False在实际业务中,如上传头像接口,可以这样使用:
def upload_avatar(request):
"""用户上传新头像"""
with raise_api_error(KeyError, 'AVATAR_FILE_NOT_PROVIDED'):
avatar_file = request.FILES['avatar']
with raise_api_error(ResizeAvatarError, 'AVATAR_FILE_INVALID'),\
raise_api_error(FileTooLargeError, 'AVATAR_FILE_TOO_LARGE'):
resized_avatar_file = resize_avatar(avatar_file)
with raise_api_error(Exception, 'INTERNAL_SERVER_ERROR'):
request.user.avatar = resized_avatar_file
request.user.save()
return HttpResponse({})


以上就是Python工程实践:从项目结构到异常处理的8个关键建议的详细内容,更多关于Python编程技巧的资料请关注本站其它相关文章!
本站声明
本文内容仅供参考,不代表本站观点。转载或引用请注明出处。如发现内容问题,请通过联系我们页面反馈。













