英文:
Why does 'import dataclasses' cause logging to stop working?
问题
我有以下的代码:
import logging
# import dataclasses
logging.basicConfig(
filename="logfile.log",
level=logging.DEBUG,
)
def main():
logging.info("This is an info message")
logging.error("This is an error message")
if __name__ == "__main__":
main()
如果我注释掉 import dataclasses
,日志将正常输出。但如果包括 import dataclasses
,日志将完全停止输出。
有人知道为什么会这样吗?可能是个bug吗?
Python版本:3.9.16
英文:
I have the follow bit of code:
import logging
# import dataclasses
logging.basicConfig(
filename="logfile.log",
level=logging.DEBUG,
)
def main():
logging.info("This is an info message")
logging.error("This is an error message")
if __name__ == "__main__":
main()
If I comment out import dataclasses
the logs are outputted properly. But if I include import dataclasses
it stops outputting completely.
Does anyone know why this is? Perhaps a bug?
Python version: 3.9.16
答案1
得分: 0
以下是您要翻译的内容:
这里似乎是导致我的问题的原因。我有以下简化的项目布局:
project/
script_one/
script_one.py
script_two/
script_two.py
script_one.py:
import logging
logging.basicConfig(
filename="script_one.log",
level=logging.DEBUG,
)
def main() -> None:
logging.info("Starting script...")
if __name__ == "__main__":
main()
script_two.py:
import logging
import dataclasses
logging.basicConfig(
filename="logfile.log",
level=logging.DEBUG,
)
def main():
logging.info("This is an info message")
logging.error("This is an error message")
if __name__ == "__main__":
main()
问题在于script_one.py
也在主函数之外包含了logging.basicConfig
。显然,这导致了script_two.py
中的日志输出到script_one.log
,尽管只运行了script_two.py
(这些脚本不相互导入)。
我好奇为什么Python会这样工作...
还有为什么import dataclasses
会触发这个问题...
无论如何,解决方案是只需使用一个单独的记录器函数,并从主函数初始化:
script_one.py:
import logging
def logger():
logging.basicConfig(
filename="script_one.log",
level=logging.DEBUG,
)
def main() -> None:
logger()
logging.info("Starting script...")
if __name__ == "__main__":
main()
script_two.py:
import logging
import dataclasses
def logger():
logging.basicConfig(
filename="logfile.log",
level=logging.DEBUG,
)
def main():
logger()
logging.info("This is an info message")
logging.error("This is an error message")
if __name__ == "__main__":
main()
----------------------编辑----------------------
我现在完全明白了在script_one.py
中添加import traceback; traceback.print_stack()
后发生的情况,正如@user2357112建议的那样:
File "/home/user/project/script_two/script_two.py", line 5, in <module>
from dataclasses import dataclass
File "<frozen importlib._bootstrap>", line 1007, in _find_and_load
File "<frozen importlib._bootstrap>", line 986, in _find_and_load_unlocked
File "<frozen importlib._bootstrap>", line 680, in _load_unlocked
File "<frozen importlib._bootstrap_external>", line 850, in exec_module
File "<frozen importlib._bootstrap>", line 228, in _call_with_frames_removed
File "/usr/lib/python3.9/dataclasses.py", line 3, in <module>
import copy
File "<frozen importlib._bootstrap>", line 1007, in _find_and_load
File "<frozen importlib._bootstrap>", line 986, in _find_and_load_unlocked
File "<frozen importlib._bootstrap>", line 680, in _load_unlocked
File "<frozen importlib._bootstrap_external>", line 850, in exec_module
File "<frozen importlib._bootstrap>", line 228, in _call_with_frames_removed
File "/home/user/project/copy/copy.py", line 8, in <module>
traceback.print_stack()
事实上,我在示例中使用的script_one.py
实际上被称为copy.py
。由于dataclasses
导入了copy
模块,它实际上导入了我的copy.py
,然后运行了日志记录语句,将日志输出到另一个文件。
谜题解决了!
英文:
So here's what seems to be causing my issue. I have the following simplified project layout:
project/
script_one/
script_one.py
script_two/
script_two.py
script_one.py:
import logging
logging.basicConfig(
filename="script_one.log",
level=logging.DEBUG,
)
def main() -> None:
logging.info("Starting script...")
if __name__ == "__main__":
main()
script_two.py:
import logging
import dataclasses
logging.basicConfig(
filename="logfile.log",
level=logging.DEBUG,
)
def main():
logging.info("This is an info message")
logging.error("This is an error message")
if __name__ == "__main__":
main()
The problem is that script_one.py
also contains logging.basicConfig
outside of the main function. Apparently this caused the logs in script_two.py
to be output to script_one.log
, despite only running script_two.py
(these scripts don't import each other).
I am curious why Python works this way...
And also why import dataclasses
triggers this issue...
Anyway, the solution is to just use a separate logger function and initialize from main:
script_one.py:
import logging
def logger():
logging.basicConfig(
filename="script_one.log",
level=logging.DEBUG,
)
def main() -> None:
logger()
logging.info("Starting script...")
if __name__ == "__main__":
main()
script_two.py:
import logging
import dataclasses
def logger():
logging.basicConfig(
filename="logfile.log",
level=logging.DEBUG,
)
def main():
logger()
logging.info("This is an info message")
logging.error("This is an error message")
if __name__ == "__main__":
main()
----------------------EDIT----------------------
I now fully understand what was happening after placing import traceback; traceback.print_stack()
in script_one.py
as suggested by @user2357112:
File "/home/user/project/script_two/script_two.py", line 5, in <module>
from dataclasses import dataclass
File "<frozen importlib._bootstrap>", line 1007, in _find_and_load
File "<frozen importlib._bootstrap>", line 986, in _find_and_load_unlocked
File "<frozen importlib._bootstrap>", line 680, in _load_unlocked
File "<frozen importlib._bootstrap_external>", line 850, in exec_module
File "<frozen importlib._bootstrap>", line 228, in _call_with_frames_removed
File "/usr/lib/python3.9/dataclasses.py", line 3, in <module>
import copy
File "<frozen importlib._bootstrap>", line 1007, in _find_and_load
File "<frozen importlib._bootstrap>", line 986, in _find_and_load_unlocked
File "<frozen importlib._bootstrap>", line 680, in _load_unlocked
File "<frozen importlib._bootstrap_external>", line 850, in exec_module
File "<frozen importlib._bootstrap>", line 228, in _call_with_frames_removed
File "/home/user/project/copy/copy.py", line 8, in <module>
traceback.print_stack()
As it so happens, my script_one.py
that I used in the example was actually called copy.py
. Since dataclasses
imports the copy
module, it instead imports my copy.py
which then runs the logging statement, outputting to the other file.
Mystery solved!
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论