【问题标题】:Global variable is undefined at the module level全局变量在模块级别未定义
【发布时间】:2015-01-02 15:11:01
【问题描述】:

(有许多类似和更通用的问题,在阅读它们后一直在尝试他们的解决方案,但无法让它们发挥作用,所以在这里作为我所看到的更具体情况的版本提出)

由于我的 C#/C++ 背景更多,我想我真的很想了解 Python 如何执行 OOP。所以这就是我现在正在尝试做的事情。

我从两个模块开始设置我的项目的其余部分,部分作为健全性检查和概念验证。一个模块在我去的时候将事情记录到一个文件中,同时还存储来自多个模块的数据(最终将它们全部打包并根据请求转储它们)在 PyCharm 中执行所有这些操作并顺便提及它建议的错误警告,并使用 Python 2.7

Module 1:
  src\helpers\logHelpers.py
    class LogHelpers:
      class log:
         def classEnter():
           #doing stuff
         def __init__(self):
           self.myLog = LogHelpers.log()  #forgot to mention this was here initially
      [..] various logging functions and variables to summarize what's happening
    __builtin__.mylogger = LogHelpers

Module 2:
  src\ULTs\myULTs.py
    mylogger.myLog.classEnter()

(模块和根 src\ 中都有一个空的 init.py 文件)

因此,根据此处完全令人敬畏的响应 (Python - Visibility of global variables in imported modules) 在此阶段这应该可以工作,但“mylogger”变成了“未解决的参考”

所以这是一种方法。我还尝试了更直接的全局方法(Python: How to make a cross-module variable?)

Module 1:
  src\helpers\logHelpers.py
    class LogHelpers:
      class log:
         def classEnter(self):
           #doing stuff
         def __init__(self):
           self.myLog = LogHelpers.log()  #forgot to mention this was here initially
      [..] various logging functions and variables to summarize what's happening
    mylogger = LogHelpers

  __init__.py
     __all__ = ['LogHelpers', hexlogger]
    from .logHelpers import * 

Module 2:
  src\ULTs\myULTs.py
    from helpers import mylogger
    mylogger.myLog.classEnter()

此版本在 classEnter 上出现“参数 'self' unfilled”错误,各种报告似乎表明 mylogger 未初始化(误导性错误代码,但这似乎是这个意思)

然后我尝试了这个..

Module 1:
  src\helpers\logHelpers.py
    class LogHelpers:
      class log:
         def classEnter(self):
           #doing stuff
         def __init__(self):
           self.myLog = LogHelpers.log()  #forgot to mention this was here initially
      [..] various logging functions and variables to summarize what's happening
    __mylogger = LogHelpers

  __init__.py
     __all__ = ['LogHelpers', hexlogger]
    from .logHelpers import * 

Module 2:
  src\ULTs\myULTs.py
    from helpers import mylogger

    def someFunction(self):
      global mylogger
      mylogger.myLog.classEnter()

当我将鼠标悬停在全局 mylogger 上时,此版本会出现“全局变量在模块级别未定义”错误。

然后是每个其他模块显然跟踪自己的类实例的想法,如果我最终不得不使用该方法并协调它们..但考虑到我正在尝试的内容,这是一种黑客行为去做。

这就是我所处的位置,这就是我想要做的事情的要点......我正在阅读尽可能多的类似问题,但所有这些问题似乎都回到了这些解决方案(似乎不起作用)或说“不要那样做”(这通常是个好建议,但我并没有真正理解为大型项目组织多个正在进行的非静态类的首选 Pythony 方式- 除了将它们全部放在一个目录中)

想法? (我在这里对 Python 的破坏有多严重?)

[编辑] 根据反馈尝试了一个完全消除内部类的迷你版本: 好的,根据您所说的,当地的迷你班也是如此:

class testClass:
    def __init__(self):
        self.testVar = 2
    def incrementVar(self):
        self.testVar += 1
myClass = testClass()

通过 init.py

进行设置
__all__ = [myClass]
from .logHelpers import myClass

去了其他模块和

from helpers import myClass
class Test_LogHelpers(unittest.TestCase):
    def test_mini(self):
        myClass.incrementVar()

直接运行它而不是看 PyCharm,没有全局任何东西..NameError: name 'myClass is not defined

所以仍然在第一格:((并且仍然需要存储状态)

[编辑] 添加回溯:

Traceback (most recent call last):
  File "C:\Program Files (x86)\JetBrains\PyCharm Community Edition 3.4.1\helpers\pycharm\utrunner.py", line 124, in <module>    module = loadSource(a[0])
  File "C:\Program Files (x86)\JetBrains\PyCharm Community Edition 3.4.1\helpers\pycharm\utrunner.py", line 40, in loadSource    module = imp.load_source(moduleName, fileName)
  File "C:\[...mylocation...]\py\src\ULTs\LogHelpers_ULT.py", line 3, in <module>    from helpers import myClass
  File "C:\[...mylocation...]\py\src\helpers\__init__.py", line 7, in <module>
    __all__ = [myClass]
NameError: name 'myClass' is not defined

================================================ ==============================

kk,我得到了它与迷你班的合作。我不知道为什么其他方法/方法不起作用,但这似乎解决了问题。 (资源:http://docs.python-guide.org/en/latest/writing/structure/,http://mikegrouchy.com/blog/2012/05/be-pythonic-__init__py.html)

**logHelpers.py**
[... some static logging functionality ...]

class testClass:
    def __init__(self):
        self.testVar = 2

    def incrementVar(self, source):
        self.testVar += 1
        mylogger.myLog.info(source + " called, new val: " + str(self.testVar))
myClass = testClass()

**test_LogHelpers_ULT.py**
import unittest

from helpers.logHelpers import myClass    

class Test_LogHelpers(unittest.TestCase):
    def test_mini(self):
        myClass.incrementVar("LogHelpers")

由于某种原因跳过 初始化.py (并将其留空)并进行显式导入工作。它还保持状态 - 我创建了测试文件的副本,并且我的日志输出正确地为第一个文件调用了帮助程序的“3”,以及第二个调用帮助程序的文件的“4”。

感谢 Daniel Roseman 的帮助和建议,他们让我更加了解了正确的方向。如果您能发现以前的东西为什么不起作用,那么只要增加我对这种语言的理解就非常感谢,但我会继续将您的答案标记为“已回答”,因为它有一些非常有用的反馈。

【问题讨论】:

    标签: python module scope global-variables


    【解决方案1】:

    在我开始之前,请注意 PyCharm 警告并不是真正的 Python 错误:如果您运行代码,您可能会获得更多有用的反馈(请记住,对 Python 等动态语言的静态分析只能让您了解很多东西在您实际运行代码之前无法解决)。

    首先,真的不清楚为什么在这里有嵌套类。外部类似乎完全没用;你应该删除它。

    关于“self”的错误信息的原因是你定义了一个实例方法,该方法只能在log的实例上调用。你可以将mylogger(绝对不需要双下划线前缀)作为一个实例:mylogger = log() - 然后导入它,或者导入类并在使用它的地方实例化它。

    所以在你的第一个 sn-p 中,错误信息很清楚:你还没有定义 mylogger。使用我上面的建议,你可以做from helpers import mylogger,然后直接调用mylogger.classEnter()。

    最后,我看不到global 语句在someFunction 中的作用。除非您计划在您的范围内重新分配名称并将该重新分配反映在全局范围中,否则无需将名称声明为全局名称。你不是在这里做的,所以不需要global。

    顺便说一句,您还应该质疑您是否甚至需要内部 log 类。一般来说,类仅在您需要在对象中存储某种状态时才有用。在这里,正如您的文档字符串所说,您拥有一组实用程序方法。那么为什么要把他们放在一个班级里呢?只需将它们设为 logHelpers 模块中的顶级函数即可(顺便说一下,Python 风格更喜欢 lower_case_with_underscore 作为模块名称,所以它应该是“log_helpers.py”)。

    【讨论】:

    • 非常感谢您的反馈 - 我会尽快尝试(今天晚些时候我再次接近代码时)我保留嵌套类,因为我想要一个单一的联系点我可以扩展为相关但服务于不同目的的不同功能。 (简单的日志记录,现在断言,稍后再说)。我可以通过拥有各种类和一个具有多个变量的类来做同样的事情,每个变量都存储一个类,只是试图将定义保持在内部,因为这些类不应该单独实现/保持自动完成清洁。
    • 确认 - 当我试图复制我尝试过的各种东西时,那些额外的 __ 是这里的错字,删除它们。
    • 好吧,记住嵌套类并没有给内部类任何对外部类的特权访问,所以它很少有任何好处。通常在 Python 中,嵌套的元素是包和模块,而不是类。
    • edit 将其移至主帖,因为格式丢失了
    • 你能显示最新错误的完整回溯吗?
    猜你喜欢
    • 2020-07-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-06-26
    • 1970-01-01
    • 2019-04-08
    • 2018-09-17
    相关资源
    最近更新 更多