需要注意的Python问题

160 阅读3分钟

1.Python 3.8中yield 的变化

随着Python 3.8的发布,对该语言进行了一些重大的补充和突破性的改变。在生成器表达式和理解式中使用yield 时,行为有了变化。

以此为例。

MAGIC_NUMBERS = {(yield num) for num in SECRET_NUMBERS if can_amaze(num)}

这在Python 3.7之前是允许的(尽管它仍然会抛出一个DeprecationWarning )--而在Python 3.8中变成了一个SyntaxError

在使用yield 时,还有一些不一致的地方需要注意。例如,在 Python 2.7 中,这不会抛出任何错误。

但是,如果像这样在列表理解中使用yield ,Python 2.7 会抛出一个SyntaxError'yield' outside function

odd _numbers =[(yield num) for num in range(100) if num % 2 == 0]

在 Python 3.x (直到 Python 3.7) 中,所有上述的操作都是允许的。从 Python 3.8 开始,这已经成为非法的了。要阅读关于这个问题的更多信息,请查看这个错误报告

2.当assert 失败时引发另一个异常是无效的

当一个assert 条件不满足时,它总是引发一个AssertionError 。即使明确地引发另一个内置的异常,也是无效的。

例子:

assert isinstance(num_channels, int), ValueError(
    'Number of image channels needs to be an integer'
)

这里,当assert失败时,用户会期待一个像这样的ValueError

ValueError: Number of image channels needs to be an integer

但相反,当条件失败时,上面的代码会抛出一个AssertionError

AssertionError: Number of image channels needs to be an integer

3.使用sqrt 方法进行毕达哥拉斯式计算

使用标准公式sqrt(a**2 + b**2) 计算斜边的长度,如果ab 或两者都很大,可能会导致OverflowError

比如说:

def get_hypotenuse(a, b):
    return math.sqrt(a**2 + b**2)

get_hypotenuse(2e154, 1e154)

运行这个公式会有这样的输出:

OverflowError: (34, 'Numerical result out of range')

为了避免这种情况,请使用math 模块中的hypot 方法。

即使提供给hypot 方法的一方(或两方)太大,无法存储(例如2e3081e154 ),也不会出现任何运行时错误,返回值为inf

4.空模块

让空模块到处乱放绝不是个好主意,因为它不必要地填充了项目。如果该文件由于某种原因是必要的,那么该文件应该有文件说明,解释它为什么在那里。

可读性很重要

5.用debug 作为运行的Flask应用True

调试器是用来在本地使用的,在生产中不应该启用。

当flask应用在调试模式下运行时,如果应用使用交互式调试器(如werkzeug ),攻击者可以获得对运行该应用的服务的访问。在这种情况下,应用程序就容易受到远程代码执行的攻击,因为任何任意代码都可以通过互动调试器运行。

下面是一个关于该漏洞的例子。

from flask import Flask

app = Flask(__name__)

@app.route('/crash')
def main():
    ...
    raise Exception()

app.run(debug=True)

推荐的方法是删除启用调试器的语句,或者在生产环境中设置环境变量来禁用它。这里有一篇关于Patreon如何因为这个漏洞而被黑的文章。