Ham*_*jan 2 python oop methods class python-2.6
我使用Python 2.6作为批处理脚本替换.它将通过双击启动,因此用户将丢失/忽略对stdout的所有输出.所以,我决定添加日志记录,为了简单起见,我为此写了一个类.我的想法是,我可以Logging.Logger
在我的代码中的任何地方使用,并且记录器将准备就绪.
我希望目录中的日志文件不超过10个,因此我手动清除旧的日志文件.我没有通过API找到这样的功能,而且我是偏执狂,并希望记录所有内容,事件是日志目录中有文件具有意外名称的事实.
所以,下面是我尝试这样的类,但是当我尝试测试(运行)它时出现错误:
>>> ================================ RESTART ================================
>>>
Traceback (most recent call last):
File "C:/AutomationScripts/build scripts/Deleteme.py", line 6, in <module>
class Logging:
File "C:/AutomationScripts/build scripts/Deleteme.py", line 42, in Logging
__clearOldLogs(dummySetting)
File "C:/AutomationScripts/build scripts/Deleteme.py", line 38, in __clearOldLogs
_assert(Logger, 'Logger does not exist yet! Why?')
NameError: global name '_assert' is not defined
>>>
Run Code Online (Sandbox Code Playgroud)
是的,我来自Java/C#背景.我可能不会做"Pythonic"的方式.请帮我做正确的事,请给出一个完整的答案,而不是简单地指出我的知识漏洞.我相信我提供了足够的代码示例.对不起,如果没有设置类,它就不会运行,但希望你明白了.
# This file has been tested on Python 2.6.*. For Windows only.
import logging # For actual logging
import tkMessageBox # To display an error (if logging is unavailable)
class Logging:
"""
Logging class provides simplified interface to logging
as well as provides some handy functions.
"""
# To be set when the logger is properly configured.
Logger = None
@staticmethod
def _assert(condition, message):
""" Like a regular assert, except that it should be visible to the user. """
if condition: return
# Else log and fail
if Logger:
Logger.debug(traceback.format_stack())
Logger.error('Assert failed: ' + message)
else:
tkMessageBox.showinfo('Assert failed: ' + message, traceback.format_stack())
assert(condition)
@staticmethod
def _removeFromEnd(string, endString):
_assert(string.endswith(endString),
"String '{0}' does not end in '{1}'.".format(string, endString))
return string[:-len(endString)]
def __clearOldLogs(logSettings):
"""
We want to clear old (by date) files if we get too many.
We should call this method only after variable 'Logger' has been created.
"""
# The following check should not be necessary from outside of
# Logging class, when it is fully defined
_assert(Logger, 'Logger does not exist yet! Why?')
# Do more work here
def __createLogger(logSettings):
logFileName = logSettings.LogFileNameFunc()
#_assert(False, 'Test')
logName = _removeFromEnd(logFileName, logSettings.FileExtension)
logFileName = os.path.join(logSettings.BaseDir, logFileName)
# If someone tried to log something before basicConfig is called,
# Python creates a default handler that goes to the console and will
# ignore further basicConfig calls. Remove the handler if there is one.
root = logging.getLogger()
if root.handlers:
for handler in root.handlers:
root.removeHandler(handler)
logging.basicConfig(filename = logFileName, name = logName, level = logging.DEBUG, format = "%(asctime)s - %(levelname)s - %(message)s")
logger = logging.getLogger(logName)
return logger
# Settings is a separate class (not dependent on this one).
Logger = __createLogger(Settings.LOGGING)
__clearOldLogs(Settings.LOGGING)
if __name__ == '__main__':
# This code section will not run when the class is imported.
# If it is run directly, then we will print debugging info.
logger = Logging.Logger
logger.debug('Test debug message.')
logger.info('Test info message.')
logger.warning('Test warning message.')
logger.error('Test error message.')
logger.critical('Test critical message.')
Run Code Online (Sandbox Code Playgroud)
欢迎提出相关问题,风格建议和完整答案.谢谢!
你得到那个例外,因为你是打电话_assert()
而不是Logging._assert()
.错误消息告诉您它正在_assert()
模块的全局命名空间而不是类命名空间中查找; 要让它查看后者,你必须明确指定它.
当然,在这种情况下,你正在尝试在类仍然被定义时执行它,并且在类完成之前名称不可用,因此要使这项工作变得困难.
一个解决方案是取消缩进以下两行(我已编辑为使用完全限定名),以便它们在类定义之外; 它们将在它之后立即执行.
Logger = Logging.__createLogger(Settings.LOGGING)
Logging.__clearOldLogs(Settings.LOGGING)
Run Code Online (Sandbox Code Playgroud)
一个样式建议将有所帮助:而不是使用一堆静态方法创建一个类,考虑将它们作为模块中的顶级函数.模块的用户(包括您自己)会发现更容易获得他们想要的功能.没有理由将一个类用作容器; 模块本身就已经是这样一个容器了.
模块基本上是一个单独的*.py
文件(虽然你可以创建具有多个文件的模块,但现在这样做).当你这样做时import
,你导入的是一个模块.在您的示例中,tkMessageBox
并且logging
都是模块.因此,只需创建一个单独的文件(确保其名称与现有的Python模块名称不冲突),将其保存在与主脚本相同的目录中,然后将其导入主脚本中.如果你对它mylogging.py
进行了命名,那么你就可以import mylogging
访问其中的函数mylogging.clearOldLogs()
或者其他函数(类似于你现在作为一个类来解决它们的方式).
Python中的"全局"名称并不是真正的全局名称,它们只是它们所定义的模块的全局名称.因此,模块是划分功能的好方法,尤其是您预期会在很多情况下重复使用的部分(如日志记录)你未来的剧本.
归档时间: |
|
查看次数: |
387 次 |
最近记录: |