python - 为什么对 sys.frozen 使用 getattr 而不是 hasattr?

标签 python pyinstaller executable cx-freeze sys

我能找到的每个文档和答案都说,为了检查程序是否“卡住”(例如 exe),我们可以使用 getattr(sys, 'frozen', False) 通过以下方式:

import sys
if getattr(sys, 'frozen', False):
    print('program is frozen exe')
else:
    print('program is a .py script')

如果 frozen 属性不存在,则默认返回 False 而不是抛出 AttributeError。来自控制台的示例:

>>> getattr(sys, 'frozen')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: module 'sys' has no attribute 'frozen'
>>> getattr(sys, 'frozen', False)
False
>>> hasattr(sys, 'frozen')
False

一切都很好,但是有一个更短的版本可以完成同样的工作,除非我遗漏了什么:

hasattr(sys, 'frozen')

它只返回 TrueFalse 而无需指定默认值。尽管它更短并且可能更易读,但每个在线文档和答案都使用 getattr 代替。我确定我可能会忽略一个巧妙的区别,这就是我问这个问题的原因。

引用 getattr 的示例源:

最佳答案

PyInstaller 文档本身使用 getattr 风格的代码块 here ,因此通过复制粘贴效应,它会激增。

那么问题就变成了:为什么 PyInstaller 文档要这样做?正如其他人在评论中所说,sys.frozen 理论上可以设置为 False 或其他一些 falsy值,在这种情况下,hasattr(sys, 'frozen') 仍会返回 True:

>>> class Stuff:
...     pass
... 
>>> x = Stuff()
>>> x.yes = True
>>> hasattr(x, 'yes')
True
>>> getattr(x, 'yes', False)
True
>>> x.no = False
>>> hasattr(x, 'no')
True
>>> getattr(x, 'no', False)
False

但正如 PyInstaller 所使用的那样,是否可以设置 sys.frozen,但使用假值?让我们检查一下源代码:

$ git clone git://github.com/pyinstaller/pyinstaller
Cloning into 'pyinstaller'...
...
$ cd pyinstaller
$ git grep '\(sys\.frozen\|frozen = \)' PyInstaller
PyInstaller/loader/pyiboot01_bootstrap.py:    sys.frozen = True
PyInstaller/utils/win32/winutils.py:            # True if "sys.frozen" is currently set.
PyInstaller/utils/win32/winutils.py:            is_sys_frozen = hasattr(sys, 'frozen')
PyInstaller/utils/win32/winutils.py:            # Current value of "sys.frozen" if any.
PyInstaller/utils/win32/winutils.py:            sys_frozen = getattr(sys, 'frozen', None)
PyInstaller/utils/win32/winutils.py:            sys.frozen = '|_|GLYH@CK'
PyInstaller/utils/win32/winutils.py:            # If "sys.frozen" was previously set, restore its prior value.
PyInstaller/utils/win32/winutils.py:                sys.frozen = sys_frozen
PyInstaller/utils/win32/winutils.py:                del sys.frozen

所以这个变量只在两种情况下设置:

  1. True,同时加载/引导;和
  2. 暂时在实用方法中'|_|GLYH@CK'

它从不从 PyInstaller 接收到虚假值。

所以在实践中,使用 hasattr(sys, 'frozen') 会很好。从正确性的角度来看,它只是感觉不对,因为它是一种处理不当的边缘情况,这可能就是 PyInstaller 文档使用 getattr 的原因:它更像是 future-proof .

关于python - 为什么对 sys.frozen 使用 getattr 而不是 hasattr?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59238237/

相关文章:

python - 在 python 3.4.3 上安装 pyinstaller

python - 是否有相当于 .NET 的 ListView 控件的 Tkinter 小部件?

python - 基本 Django 查询?

python - 使用 Pyinstaller 编译 Gekko

python - Pyinstaller无法构建wxpython应用程序,缺少错误wx._xml

c - 如何正确地逐字节读取文件而不丢失任何信息

android - 在android终端模拟器中执行python脚本

python - 使用 monit 运行和停止 Gunicorn 服务器

python - 如何确保我的 Keras/tensorflow 代码使用我的 MacBook Pro 的 AMD 显卡

python - 使用 Pyinstaller 2.0、PySide 1.1.2 绑定(bind)和 Qt 4.8 时如何在应用程序中包含图标