首页 > 解决方案 > 如何从给出变量未定义错误的模块中修复类方法函数

问题描述

所以我正在尝试创建一个更简单的日志记录模块,但我不断收到毫无意义的错误。

该模块位于%appdata%/python/site-packages/loggingLocal/__init__.py

模块代码如下:

class Logger:

    def __init__(self):

        pass

    @classmethod

    def llog(cls, file, typeM, message):

        llog_f = open(file, "a")
        llog_f.write("\n" + typeM + ": " + message)
        llog_f.close

我用来利用该模块的代码如下:

import loggingLocal.__init__

logOb = Logger()

lfile = "logs/log.txt"

logOb.llog(lfile, "test", "testing testing 1 2 3")

我希望文件logs/log.txt包含test: testing testing 1 2 3,但我收到一个错误:Undefined variable 'Logger'在第三行。这是没有意义的,因为我分配logObLogger类,而不是变量。

我想指出,我知道我没有以最有效的方式做事,但这不是我来这里的目的。

标签: pythonwindows

解决方案


当您导入一个模块时,您只会将模块的名称添加到您的本地命名空间中,而不是模块的所有内容(尽管如果您特别要求,您可以得到它)。

因此,如果您这样做import loggingLocal(不需要该__init__部分,下面将详细介绍),您将只能loggingLocal在主模块的命名空间中获得名称。要访问其中的Logger类,您需要使用loggingLocal.Logger.

或者,您可以使用替代导入语法明确说明要从导入的模块复制到您自己的命名空间中的特定名称from some_module import some_name。在你的情况下,你可能想要from loggingLocal import Logger. 如果需要,您可以给出多个名称,或者您可以给出 a*而不是任何名称,在这种情况下,您将获得模块属性中列出的任何名称__all__,或者另一个模块中具有名称的每个全局变量不要以下划线开头。

您的代码中还有其他一些小错误。我在上面提到的一个,您在声明中命名__init__模块名称的一部分import。那是不需要的。__init__.py是用于构成包根部分的模块的文件名。即foo/__init__.py成为foo模块。如果出于其他原因不需要包(例如,因为您还有foo/bar.pyand foo/baz.py,可以将其导入为foo.barand foo.baz),您可能不应该使用该结构。相反,只需将localLogging/__init__.py文件重命名为localLogging.py并删除子目录。

另一个问题是您对 Logger 的实现。当您尝试关闭您在 中创建的文件时llog,您实际上并没有成功。您只引用该close方法,但从未真正调用它(您可能想要这样做llog_f.close())。我建议使用with语句来处理文件的打开和关闭:

with open(file, "a") as llog_f:
    llog_f.write("\n" + typeM + ": " + message)

with此代码将在语句后面的缩进块末尾自动关闭文件。如果有异常导致块以异常方式退出,它甚至会关闭文件。


推荐阅读