我能找到的每个文档和答案都说,为了检查程序是否“卡住”(例如 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')
它只返回 True
或 False
而无需指定默认值。尽管它更短并且可能更易读,但每个在线文档和答案都使用 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
所以这个变量只在两种情况下设置:
- 为
True
,同时加载/引导;和 - 暂时在实用方法中
'|_|GLYH@CK'
。
它从不从 PyInstaller 接收到虚假值。
所以在实践中,使用 hasattr(sys, 'frozen')
会很好。从正确性的角度来看,它只是感觉不对,因为它是一种处理不当的边缘情况,这可能就是 PyInstaller 文档使用 getattr
的原因:它更像是 future-proof .
关于python - 为什么对 sys.frozen 使用 getattr 而不是 hasattr?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59238237/