模块与调试#
1. 基本操作#
1.1. 导入#
模块就是程序,任何以 .py
为扩展名的文件均是 python 模块,都可用 import
导入
# 方法 1
import time as t
t.sleep(1)
# 方法 2 (导入整个包,可直接使用包中的模块)
from time import sleep
sleep(1)
# 重新导入
import imp
imp.reload(模块名)
1.2. 查看路径和帮助#
# 方法 1
import os
os.__file__
#方法 2
import sys
sys.path
2. 模块的制作#
2.1. 头文件#
import
会执行对象的全部代码,为使其中的部分代码在导入时不被调用,必须加入头文件。
当模块调用自身的name方法,执行的是字符串 '__main__'
,当调用其他模块的 __name__
,执行的是字符串’调用模块名’。添加 if __name__=='__main__':
可使下面的代码只有在调用时执行,被导入时不执行。
# 模块末尾往往会添加
def main():
pass
if __name__=='__main__':
main()
2.2. 起始文件#
创建 1 个存放相关模块的文件夹,文件夹的名字即包(Package)的名字
在文件夹中创建 1 个起始文件
__init__.py
,内容可为空,也会写入__all__
方法。__all__=[]
中的元素,可被from xxx import *
导入,其中的元素可是’类名’,也可是’方法名’,但均是str
。
# setup.py 的编写
from setuptools import setup, find_packages
setup(name='package',
description='',
version='',
author='',
py_modules=['package.module'])
find_packages()
# __init__.py
__version__ = ''
3. 异常#
3.1. 异常的捕获#
在编写函数的时候,需要处理错误输入,并给出错误信息,这个时候需要编写异常函数。
有异常处理的函数,在异常处理后会继续执行
没有异常处理的函数,将停止执行后面的代码,并将异常传递给外层函数。
异常类型 |
|
---|---|
|
文件打开异常 |
|
类型异常 |
|
名称异常 |
|
未找到文件 |
|
所有异常的父类 |
在编写实用函数的时候,Python 有一个吸引人的地方,就是赋予 None
的返回值以特殊意义。在某些情况下,这似乎是有道理的。例如,如说我想要一个帮助函数,用一个数字除以另一个数字。在除以 0 的情况下,返回 None
似乎很自然,因为结果是未定义的。返回 None
表示特殊含义的函数容易出错,因为在条件表达式中,None
和其他值(如零、空字符串)都会被评价为 False
。故使用异常的方法更为合理。
def careful_divide(a, b):
try:
return a / b
except ZeroDivisionError as e:
raise ValueError('Invalid inputs')
x, y = 5, 2
try:
result = careful_divide(x, y)
except ValueError:
print('Invalid inputs')
else:
print(f'Result is {result:.1f}')
3.2. 异常的自定义#
raise
语句可用于来引发异常,若后面没有关键字,则引发相应异常。异常类的名字可自定义,但必须继承自 Error
或 Exception
。
class InputException(Exception):
def __init__(self, length, atleast):
super().__init__()
self.length = length
self.atleast = atleast
def main():
try:
s = input('输入:')
if len(s) < 3:
raise InputException(len(s), 3)
except InputException as result:
print(f'输入的长度是{result.length},长度至少应是{result.atleast}')
else:
print('没有异常发生')
main()
3.3. 迭代异常#
Python 在生成器中提供了 throw()
方法来处理频繁使用 yield
部分的异常,但这种方法会破坏可读性。推荐构建类,并使用 __iter__()
方法来处理还有循环和 yield
的部分。
class Timer:
def __init__(self, period):
self.current = period
self.period = period
def reset(self):
self.current = self.period
def __iter__(self):
while self.current:
self.current -= 1
yield self.current
4. 消除 if
#
4.1. 嵌套 if
#
在函数内使用 return
或 raise
等语句提前在分支内结束函数。
def buy_fruit(nerd, store):
"""去水果店买苹果
- 先得看看店是不是在营业
- 若有苹果的话,就买 1 个
- 若钱不够,就回家取钱再来
"""
if store.is_open():
if store.has_stocks("apple"):
if nerd.can_afford(store.price("apple", amount=1)):
nerd.buy(store, "apple", amount=1)
return
else:
nerd.go_home_and_get_money()
return buy_fruit(nerd, store)
else:
raise MadAtNoFruit("no apple in store!")
else:
raise MadAtNoFruit("store is closed!")
改写成
def buy_fruit(nerd, store):
if not store.is_open():
raise MadAtNoFruit("store is closed!")
if not store.has_stocks("apple"):
raise MadAtNoFruit("no apple in store!")
if nerd.can_afford(store.price("apple", amount=1)):
nerd.buy(store, "apple", amount=1)
return
else:
nerd.go_home_and_get_money()
return buy_fruit(nerd, store)
4.2. 重叠 if
#
# 对于新用户,创建新的用户资料,否则更新旧资料
if user.no_profile_exists:
create_user_profile(
username=user.username,
email=user.email,
age=user.age,
address=user.address,
# 对于新建用户,将用户的积分置为 0
points=0,
created=now(),
)
else:
update_user_profile(
username=user.username,
email=user.email,
age=user.age,
address=user.address,
updated=now(),
)
改写成
if user.no_profile_exists:
profile_func = create_user_profile
extra_args = {'points': 0, 'created': now()}
else:
profile_func = update_user_profile
extra_args = {'updated': now()}
profile_func(
username=user.username,
email=user.email,
age=user.age,
address=user.address,
**extra_args
)
5. 命令行#
5.1. 查询#
上个变量返回值:
_
包路径:
python3 -m site
5.2. 查看#
JSON:
python -m json.tool [file].json
服务器:
python3 -m http.server 8888
5.3. 文件处理#
创建 tar:
python3 -m tarfile -c [file].tar [folder]
解压 tar:
python3 -m tarfile -e [file].tar [new_file]
创建 gz:
python3 -m gzip [folder]
解压 gz:
python3 -m gzip -d [file].gz
创建 zip:
python3 -m zipfile -c [file].zip [folder]
解压 zip:
python3 -m zipfile -e [file].zip [file]