doc: 阅读python文档
This commit is contained in:
437
python/py.md
437
python/py.md
@@ -57,14 +57,19 @@
|
||||
- [dir](#dir)
|
||||
- [package](#package)
|
||||
- [from ... import \*](#from--import-)
|
||||
- [异常处理](#异常处理)
|
||||
- [抛异常](#抛异常)
|
||||
- [捕获异常后重新抛出异常](#捕获异常后重新抛出异常)
|
||||
- [主动抛出异常](#主动抛出异常)
|
||||
- [数据存储](#数据存储)
|
||||
- [json.dump](#jsondump)
|
||||
- [json.load](#jsonload)
|
||||
- [http api](#http-api)
|
||||
- [Errors and Exceptions](#errors-and-exceptions)
|
||||
- [Syntax Errors](#syntax-errors)
|
||||
- [Exceptions](#exceptions)
|
||||
- [handling exceptions](#handling-exceptions)
|
||||
- [python异常结构](#python异常结构)
|
||||
- [rasing exception](#rasing-exception)
|
||||
- [Exception Chaining](#exception-chaining)
|
||||
- [用户自定义异常类型](#用户自定义异常类型)
|
||||
- [define cleanup action](#define-cleanup-action)
|
||||
- [predefined clean-up action](#predefined-clean-up-action)
|
||||
- [rasing multi exceptions](#rasing-multi-exceptions)
|
||||
- [except\*](#except)
|
||||
- [enriching exceptions with notes](#enriching-exceptions-with-notes)
|
||||
- [多线程](#多线程)
|
||||
- [linux命令交互](#linux命令交互)
|
||||
- [正则](#正则)
|
||||
@@ -786,124 +791,338 @@ echo.echofilter(input, output, delay=0.7, atten=4)
|
||||
__all__ = ["echo", "surround", "reverse"]
|
||||
```
|
||||
|
||||
## 异常处理
|
||||
在python中,可以通过如下语法来进行异常处理
|
||||
## Errors and Exceptions
|
||||
在python中存在两种不同的异常,`syntax erros`和`exceptions`
|
||||
|
||||
### Syntax Errors
|
||||
syntax errors又被称为parsing errors,当parser检测到语法错误时,会抛出该error
|
||||
|
||||
### Exceptions
|
||||
在python程序执行时,即使语法都正常,也有可能在执行时发生异常。在程序执行时被检测到的异常被称为`exceptions`,但是其时可以被处理的,并不会无条件的造成fatal。
|
||||
|
||||
### handling exceptions
|
||||
可以在程序中对特定类型的异常进行处理,示例如下所示:
|
||||
```py
|
||||
while True:
|
||||
try:
|
||||
x = int(input("Please enter a number: "))
|
||||
break
|
||||
except ValueError:
|
||||
print("Oops! That was no valid number. Try again...")
|
||||
```
|
||||
上述示例中针对`ValueError`类型的异常进行了捕获,并提示用户输入有效的数字。但是,在上述程序实例中,用户仍然能够通过`Ctrl + C`中断该程序。
|
||||
|
||||
> `Ctrl + C`将会以抛出`KeyboardInterrupt`的形式表现。
|
||||
|
||||
try statement中可以包含多个except,为不同类型的异常指定handler,最多只会有一个handler被执行。并且,一个except中也可以包含多个exceptions,示例如下所示:
|
||||
```py
|
||||
... except (RuntimeError, TypeError, NameError):
|
||||
... pass
|
||||
```
|
||||
包含多个except的示例如下所示:
|
||||
```py
|
||||
class B(Exception):
|
||||
pass
|
||||
|
||||
class C(B):
|
||||
pass
|
||||
|
||||
class D(C):
|
||||
pass
|
||||
|
||||
for cls in [B, C, D]:
|
||||
try:
|
||||
raise cls()
|
||||
except D:
|
||||
print("D")
|
||||
except C:
|
||||
print("C")
|
||||
except B:
|
||||
print("B")
|
||||
```
|
||||
上述示例中,会输出`B, C, D`。但是,如果修改`except B`的位置为第一位,那么输出将会变为`B, B, B`。
|
||||
|
||||
在except语法中,除了指定异常类型外,还支持指定一个变量名来捕获异常,该变量中包含`args`属性,能够访问`构造该异常对象时传递的参数`,并且,异常中还定义了`__str__()`方法用于打印所有的异常参数。
|
||||
|
||||
为捕获的异常绑定变量的示例如下所示:
|
||||
```py
|
||||
try:
|
||||
# code block
|
||||
pass
|
||||
except ErrorType1:
|
||||
# error type 1 handling code block
|
||||
pass
|
||||
except ErrorType2:
|
||||
# error type 2 handling code block
|
||||
pass
|
||||
except Exception as result:
|
||||
# handle other exception types
|
||||
pass
|
||||
else:
|
||||
# code block that no error occurs
|
||||
pass
|
||||
finally:
|
||||
# code block executed whether exception occurs
|
||||
pass
|
||||
raise Exception('spam', 'eggs')
|
||||
except Exception as inst:
|
||||
print(type(inst)) # the exception type
|
||||
print(inst.args) # arguments stored in .args
|
||||
print(inst) # __str__ allows args to be printed directly,
|
||||
# but may be overridden in exception subclasses
|
||||
x, y = inst.args # unpack args
|
||||
print('x =', x)
|
||||
print('y =', y)
|
||||
|
||||
```
|
||||
|
||||
### 抛异常
|
||||
#### 捕获异常后重新抛出异常
|
||||
如果python在捕获异常后需要重新对异常进行抛出,可以使用`raise`关键字
|
||||
输出内容为:
|
||||
```
|
||||
<class 'Exception'>
|
||||
('spam', 'eggs')
|
||||
('spam', 'eggs')
|
||||
x = spam
|
||||
y = eggs
|
||||
```
|
||||
#### python异常结构
|
||||
`BaseException`是所有异常类的common base class;而`Exception`类则是`BaseException`的子类,同时也是所有非fatal异常类的base class。
|
||||
|
||||
对于是`BaseException`子类但是不是`Exception`子类的类,其通常代表不应当被处理的异常,抛出该类异常通常代表程序应当被终止,其包含如下类:
|
||||
- `SystemExit`:由`system.exit()`抛出
|
||||
- `KeyboardInterrupt`:由想要中止程序的用户触发`Ctrl + C`
|
||||
|
||||
`Exception`可以被用做匹配所有异常。
|
||||
```py
|
||||
import sys
|
||||
|
||||
try:
|
||||
m = 10/0
|
||||
except Exception as e:
|
||||
print(e)
|
||||
f = open('myfile.txt')
|
||||
s = f.readline()
|
||||
i = int(s.strip())
|
||||
except OSError as err:
|
||||
print("OS error:", err)
|
||||
except ValueError:
|
||||
print("Could not convert data to an integer.")
|
||||
except Exception as err:
|
||||
print(f"Unexpected {err=}, {type(err)=}")
|
||||
raise
|
||||
finally:
|
||||
print("handle correctly")
|
||||
```
|
||||
#### 主动抛出异常
|
||||
主动抛出异常时,也可使用`raise`关键字
|
||||
```py
|
||||
try:
|
||||
raise Exception("fucking Nvidia raised their price!")
|
||||
except Exception as e:
|
||||
print(e)
|
||||
finally:
|
||||
print("my wallet is empty!")
|
||||
```
|
||||
|
||||
## 数据存储
|
||||
### json.dump
|
||||
可以通过`json.dump`方法将内容以json的格式存储到文件中:
|
||||
`try-except`语法还支持`else`,`else`必须跟在所有`except`之后,其代表`try block`中没有抛出任何异常的场景。
|
||||
|
||||
```py
|
||||
import json
|
||||
|
||||
|
||||
def save_as_json(data, fd):
|
||||
json.dump(data, fd)
|
||||
|
||||
|
||||
waifu = {
|
||||
"name": "Touma Kazusa",
|
||||
"job": "Student",
|
||||
"gender": "female",
|
||||
"age": 17
|
||||
}
|
||||
|
||||
is_save_success = True
|
||||
try:
|
||||
with open("shiro.json", "w") as shiro_fd:
|
||||
save_as_json(waifu, shiro_fd)
|
||||
except Exception as e:
|
||||
print(e)
|
||||
is_save_success = False
|
||||
exit(1)
|
||||
finally:
|
||||
if is_save_success:
|
||||
print("save success!")
|
||||
for arg in sys.argv[1:]:
|
||||
try:
|
||||
f = open(arg, 'r')
|
||||
except OSError:
|
||||
print('cannot open', arg)
|
||||
else:
|
||||
print(arg, 'has', len(f.readlines()), 'lines')
|
||||
f.close()
|
||||
```
|
||||
### json.load
|
||||
可以通过`json.load`方法读取文件中的json格式内容:
|
||||
|
||||
### rasing exception
|
||||
`raise`关键字支持抛出异常,示例如下
|
||||
```py
|
||||
import json
|
||||
|
||||
|
||||
def read_as_json(fd):
|
||||
return json.load(fd)
|
||||
|
||||
|
||||
is_read_success = True
|
||||
try:
|
||||
with open("shiro.json", "r") as shiro_fd:
|
||||
r_obj = read_as_json(shiro_fd)
|
||||
print(r_obj)
|
||||
except Exception as e:
|
||||
print(e)
|
||||
is_read_success = False
|
||||
exit(1)
|
||||
finally:
|
||||
if is_read_success:
|
||||
print("read success!")
|
||||
raise NameError('HiThere')
|
||||
```
|
||||
## http api
|
||||
python安装requests包之后,可以访问http接口
|
||||
传递给raise的必须是`Exception`的实例或是`继承自Exception的类`,但传递的是类时,其会使用类的默认构造器来构造Exception实例。
|
||||
```py
|
||||
raise ValueError # shorthand for 'raise ValueError()'
|
||||
```
|
||||
`raise`关键字也能用于对异常的重新抛出,示例如下:
|
||||
```py
|
||||
import math
|
||||
import requests
|
||||
import time
|
||||
|
||||
try:
|
||||
body = requests.get("https://api.m.taobao.com/rest/api3.do", {
|
||||
"api": "mtop.common.getTimestamp"
|
||||
}).json()
|
||||
ts = body['data']['t']
|
||||
t = time.localtime(math.trunc(int(ts) / 1000))
|
||||
time_str = time.strftime("%Y-%m-%d %H:%M:%S %z", t)
|
||||
print(time_str)
|
||||
except Exception as e:
|
||||
print(e)
|
||||
raise NameError('HiThere')
|
||||
except NameError:
|
||||
print('An exception flew by!')
|
||||
raise
|
||||
```
|
||||
### Exception Chaining
|
||||
如果在`except`处理异常时,处理逻辑又抛出了异常,那么其会将被处理的异常关联到新异常中,并且将被处理异常包含在error msg中:
|
||||
```py
|
||||
try:
|
||||
open("database.sqlite")
|
||||
except OSError:
|
||||
raise RuntimeError("unable to handle error")
|
||||
```
|
||||
其输出如下:
|
||||
```
|
||||
Traceback (most recent call last):
|
||||
File "<stdin>", line 2, in <module>
|
||||
open("database.sqlite")
|
||||
~~~~^^^^^^^^^^^^^^^^^^^
|
||||
FileNotFoundError: [Errno 2] No such file or directory: 'database.sqlite'
|
||||
|
||||
During handling of the above exception, another exception occurred:
|
||||
|
||||
Traceback (most recent call last):
|
||||
File "<stdin>", line 4, in <module>
|
||||
raise RuntimeError("unable to handle error")
|
||||
RuntimeError: unable to handle error
|
||||
```
|
||||
|
||||
如果想要设置异常的cause,可以使用`from`语法,示例如下所示:
|
||||
```py
|
||||
def func():
|
||||
raise ConnectionError
|
||||
|
||||
try:
|
||||
func()
|
||||
except ConnectionError as exc:
|
||||
raise RuntimeError('Failed to open database') from exc
|
||||
```
|
||||
上述示例中,`raise ... from exc`直接表明RuntimeError由exc引发。
|
||||
|
||||
输出示例如下所示:
|
||||
```py
|
||||
Traceback (most recent call last):
|
||||
File "<stdin>", line 2, in <module>
|
||||
func()
|
||||
~~~~^^
|
||||
File "<stdin>", line 2, in func
|
||||
ConnectionError
|
||||
|
||||
The above exception was the direct cause of the following exception:
|
||||
|
||||
Traceback (most recent call last):
|
||||
File "<stdin>", line 4, in <module>
|
||||
raise RuntimeError('Failed to open database') from exc
|
||||
RuntimeError: Failed to open database
|
||||
```
|
||||
通过`from None`也可以关闭异常chain,示例如下:
|
||||
```py
|
||||
try:
|
||||
open('database.sqlite')
|
||||
except OSError:
|
||||
raise RuntimeError from None
|
||||
```
|
||||
示例如下所示:
|
||||
```py
|
||||
Traceback (most recent call last):
|
||||
File "<stdin>", line 4, in <module>
|
||||
raise RuntimeError from None
|
||||
RuntimeError
|
||||
```
|
||||
### 用户自定义异常类型
|
||||
用户如果要自定义异常,可以创建`Exception`类型的子类。
|
||||
|
||||
大多数异常类型都以`Error`结尾,和standard exceptions的命名规范类似。
|
||||
|
||||
### define cleanup action
|
||||
python支持通过`finally`来定义clean-up action,其在所有场景下都会被处理。
|
||||
```py
|
||||
try:
|
||||
raise KeyboardInterrupt
|
||||
finally:
|
||||
print('Goodbye, world!')
|
||||
```
|
||||
其中,finally执行时机如下:
|
||||
- 当抛出异常时,如果异常没有被except处理,那么异常在finally执行完后再次抛出
|
||||
- 当except或else中抛出异常时,那么异常在finally执行完后被抛出
|
||||
- 如果在finally中执行了`break, continue, return`等语句,那么异常不会被抛出
|
||||
- 如果try中执行了`break, continue, return`,那么finally会在`break, continue, return`执行之前执行
|
||||
- 如果finally中执行了return操作,那么其return的值将会覆盖try中return的值
|
||||
|
||||
finally通常被用于释放资源等操作。
|
||||
|
||||
### predefined clean-up action
|
||||
部分对象定义了对象不在被需要时的clean-up action,无论针对对象的操作是否成功,clean-up action都会被执行。
|
||||
|
||||
故而,可以通过`with`对该类对象进行使用,并无需手动释放其资源,示例如下:
|
||||
```py
|
||||
with open("myfile.txt") as f:
|
||||
for line in f:
|
||||
print(line, end="")
|
||||
```
|
||||
在上述代码执行完后,文件会自动关闭,即使是在执行过程中遇到异常。
|
||||
|
||||
### rasing multi exceptions
|
||||
在部分时候,可能需要抛出多个异常,此时可以通过`ExceptionGroup`来对exception list进行wrap,示例如下:
|
||||
```py
|
||||
def f():
|
||||
excs = [OSError('error 1'), SystemError('error 2')]
|
||||
raise ExceptionGroup('there were problems', excs)
|
||||
```
|
||||
|
||||
#### except*
|
||||
当使用`except*`时,可以选择性处理group中特定类型的异常,并将其他异常传递到下游。
|
||||
|
||||
```py
|
||||
def f():
|
||||
raise ExceptionGroup(
|
||||
"group1",
|
||||
[
|
||||
OSError(1),
|
||||
SystemError(2),
|
||||
ExceptionGroup(
|
||||
"group2",
|
||||
[
|
||||
OSError(3),
|
||||
RecursionError(4)
|
||||
]
|
||||
)
|
||||
]
|
||||
)
|
||||
|
||||
try:
|
||||
f()
|
||||
except* OSError as e:
|
||||
print("There were OSErrors")
|
||||
except* SystemError as e:
|
||||
print("There were SystemErrors")
|
||||
```
|
||||
### enriching exceptions with notes
|
||||
当创建异常时,可以通过`add_note(note)`方法来为异常补充信息,标准的traceback会按照其被添加的顺序渲染所有的note信息,note信息在异常信息之后
|
||||
```py
|
||||
try:
|
||||
raise TypeError('bad type')
|
||||
except Exception as e:
|
||||
e.add_note('Add some information')
|
||||
e.add_note('Add some more information')
|
||||
raise
|
||||
```
|
||||
其输出如下:
|
||||
```py
|
||||
Traceback (most recent call last):
|
||||
File "<stdin>", line 2, in <module>
|
||||
raise TypeError('bad type')
|
||||
TypeError: bad type
|
||||
Add some information
|
||||
Add some more information
|
||||
```
|
||||
```py
|
||||
def f():
|
||||
raise OSError('operation failed')
|
||||
|
||||
excs = []
|
||||
for i in range(3):
|
||||
try:
|
||||
f()
|
||||
except Exception as e:
|
||||
e.add_note(f'Happened in Iteration {i+1}')
|
||||
excs.append(e)
|
||||
|
||||
raise ExceptionGroup('We have some problems', excs)
|
||||
```
|
||||
其异常信息如下:
|
||||
```
|
||||
+ Exception Group Traceback (most recent call last):
|
||||
| File "<stdin>", line 1, in <module>
|
||||
| raise ExceptionGroup('We have some problems', excs)
|
||||
| ExceptionGroup: We have some problems (3 sub-exceptions)
|
||||
+-+---------------- 1 ----------------
|
||||
| Traceback (most recent call last):
|
||||
| File "<stdin>", line 3, in <module>
|
||||
| f()
|
||||
| ~^^
|
||||
| File "<stdin>", line 2, in f
|
||||
| raise OSError('operation failed')
|
||||
| OSError: operation failed
|
||||
| Happened in Iteration 1
|
||||
+---------------- 2 ----------------
|
||||
| Traceback (most recent call last):
|
||||
| File "<stdin>", line 3, in <module>
|
||||
| f()
|
||||
| ~^^
|
||||
| File "<stdin>", line 2, in f
|
||||
| raise OSError('operation failed')
|
||||
| OSError: operation failed
|
||||
| Happened in Iteration 2
|
||||
+---------------- 3 ----------------
|
||||
| Traceback (most recent call last):
|
||||
| File "<stdin>", line 3, in <module>
|
||||
| f()
|
||||
| ~^^
|
||||
| File "<stdin>", line 2, in f
|
||||
| raise OSError('operation failed')
|
||||
| OSError: operation failed
|
||||
| Happened in Iteration 3
|
||||
+------------------------------------
|
||||
```
|
||||
|
||||
## 多线程
|
||||
python可以通过引入threading和concurrent.futures两个包来引入多线程:
|
||||
|
||||
Reference in New Issue
Block a user