简体   繁体   English

全局变量在模块级别未定义

[英]Global variable is undefined at the module level

(There are many similar and more generic questions, been trying the solutions from them after reading through them, can't get them working so asking here as a more situation-specific version of what I'm seeing) (有许多类似的和更通用的问题,在阅读完它们之后一直在试用它们的解决方案,不能让它们工作所以在这里要求我看到的更具特定情况的版本)

I think I am really miss-understanding how Python does OOP due to my more C#/C++ background. 我认为我真的很想念 - 由于我更多的C#/ C ++背景,Python如何处理OOP。 So here's what I'm trying to do right this moment. 所以这就是我现在正在努力做的事情。

I'm starting with two modules to set up the rest of my project, partially as a sanity-check and proof-of-concept. 我从两个模块开始设置项目的其余部分,部分是作为一个完整性检查和概念验证。 One module logs things to a file as I go while also storing data from multiple modules (to eventually package them all and dump them on request) Doing all this in PyCharm and mentioning the error warnings it suggests by the way, and using Python 2.7 一个模块将内容记录到文件中,同时还存储来自多个模块的数据(最终将它们打包并根据请求转储它们)在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()

(both the modules and the root src\\ have an empty init .py file in them) (模块和根src \\中都有一个空的init .py文件)

So according to the totally awesome response here ( Python - Visibility of global variables in imported modules ) at this stage this should be working, but 'mylogger' becomes an 'unresolved reference' 因此,根据这里非常棒的响应( Python - 导入模块中的全局变量的可见性 ),这应该是有效的,但是'mylogger'成为'未解析的引用'

So that was one approach. 这是一种方法。 I also tried the more straight forward global one ( Python: How to make a cross-module variable? ) 我也尝试过更直接的全局变量Python:如何制作跨模块变量?

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()

This version gets a "parameter 'self' unfilled" error on the classEnter, which various reports seem to indicate means that mylogger is un-initialized (misleading error code but that's what it seems to mean) 这个版本在classEnter上得到一个“参数'自'未填充'错误,各种报告似乎表明mylogger未初始化(误导错误代码,但这似乎意味着什么)

And then I tried this.. 然后我试了这个..

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()

And this version gets the 'Global variable is undefined at the module level' error when I hover of global mylogger. 当我将鼠标悬停在全局mylogger上时,此版本会出现“模块级别未定义全局变量”错误。

Then there is the idea of each other module tracking its own instance of a class apparently, if I end up having to I can go with that method and coordinate them.. but that's kind of a hack considering what I'm trying to do. 然后有一个想法是每个其他模块显然跟踪它自己的一个类的实例,如果我最终不得不使用该方法并协调它们......但考虑到我正在尝试做什么,这就是一种黑客攻击。

That's kind of where I'm at, that's the gist of what I'm trying to do... I'm reading through as many similar questions as I can but all of them seem to come back to these kinda of solutions (which don't seem to be working) or saying 'don't do that' (which is generally good advice but I'm not really grocking the preferred Pythony way of keeping multiple ongoing non-static classes organized for a large project - other than shoving them all in one directory) 这就是我所处的位置,这就是我要做的事情的要点......我正在阅读尽可能多的类似问题,但所有这些问题似乎都回到了这些解决方案(其中似乎没有工作)或说'不要那样做'(这通常是一个很好的建议,但我并没有真正讨厌保留为大型项目组织的多个正在进行的非静态类的首选Pythony方式 - 除了将它们全部推到一个目录中)

Thoughts? 思考? (How badly am I mangling Python here?) (我在这里破坏Python有多糟糕?)

[EDIT] Based on feedback tried a mini version that eliminated the inner classes completely: Ok, so did a local mini-class based on what you said: [编辑]根据反馈尝试了一个迷你版本完全消除了内部类:好吧,基于你所说的本地小型课程也是如此:

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

Set it up via init .py 通过init .py进行设置

__all__ = [myClass]
from .logHelpers import myClass

Went to other module and 去了其他模块和

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

Ran it directly instead of looking at PyCharm, no Global anything.. NameError: name 'myClass is not defined 直接使用它而不是查看PyCharm,没有全局任何东西.. NameError: name 'myClass is not defined

So still at square one :( (and still need to store state) 所以仍然在方形一:((仍然需要存储状态)

[EDIT] Adding Traceback: [编辑]添加回溯:

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, I got it working with the miniclass. kk,我让它与miniclass一起工作。 I don't know why the other approach / approaches was not working, but this seemed to fix things. 我不知道为什么其他方法/方法不起作用,但这似乎解决了问题。 (Resources: http://docs.python-guide.org/en/latest/writing/structure/ , http://mikegrouchy.com/blog/2012/05/be-pythonic-__init__py.html ) (参考资料: 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")

For some reason skipping the init .py (and leaving it blank) and going for the explicit importation worked. 出于某种原因,跳过init .py(并将其留空)并进行显式导入工作。 It also maintained state - I created a duplicate of the test file and my log output correctly had '3' for the first file to call the helper, and '4' for the second file to call the helper. 它还保持状态 - 我创建了测试文件的副本,我的日志输出正确地为第一个调用助手的文件'3',并为第二个文件调用帮助器'4'。

Thanks Daniel Roseman for the help and suggestions, they had me look a bit more in the right direction. 感谢Daniel Roseman的帮助和建议,他们让我看起来朝着正确的方向前进。 If you can spot why the previous stuff wasn't working it would be much appreciate just to add to my understanding of this language, but I'm gonna go ahead and mark your answer as 'Answered' since it had some very useful feedback. 如果你能发现为什么以前的东西不能正常工作,那么我会非常感激地加入我对这种语言的理解,但是我会继续把你的答案标记为'已回答',因为它有一些非常有用的反馈。

Before I start, note that the PyCharm warnings are not actual Python errors: if you ran your code, you would probably get more useful feedback (remember static analysis of a dynamic language like Python can only get you so far, many things can't be resolved until you actually run the code). 在我开始之前,请注意PyCharm警告不是实际的Python错误:如果你运行你的代码,你可能会得到更多有用的反馈(记得像Python这样的动态语言的静态分析只能让你到目前为止,许多事情都不能解决,直到您实际运行代码)。

Firstly, it's really not clear why you have nested classes here. 首先,你真的不清楚为什么你在这里有嵌套类。 The outer class seems completely useless; 外层阶级似乎完全没用; you should remove it. 你应该删除它。

The reason for the error message about "self" is that you have defined an instance method, which can only be called on an instance of log . 关于“self”的错误消息的原因是您已定义了一个实例方法,该方法只能在log实例上调用。 You could make mylogger (absolutely no need for the double-underscore prefix) an instance: mylogger = log() - and then import that, or import the class and instantiate it where it is used. 你可以创建一个mylogger (绝对不需要双下划线前缀)一个实例: mylogger = log() - 然后导入它,或者导入类并在使用它的地方实例化它。

So in your first snippet, the error message is quite clear: you have not defined mylogger . 因此,在您的第一个代码段中,错误消息非常明确:您尚未定义mylogger Using my recommendation above, you can do from helpers import mylogger and then directly call mylogger.classEnter() . 使用上面的推荐,您可以from helpers import mylogger ,然后直接调用mylogger.classEnter()

Finally, I can't see what that global statement is doing in someFunction . 最后,我看不出那个global声明在someFunction做了someFunction There's no need to declare a name as global unless you plan to reassign it within your scope and have that reassignment reflected in the global scope. 除非您计划在范围内重新分配名称并将该重新分配反映在全局范围内,否则无需将名称声明为全局名称。 You're not doing that here, so no need for global . 你不是在这里做的,所以不需要global

By the way, you should also question whether you even need the inner log class. 顺便说一句,你还应该质疑你是否需要内部log类。 Generally speaking, classes are only useful when you need to store some kind of state in the object. 一般来说,只有在需要在对象中存储某种状态时,类才有用。 Here, as your docstring says, you have a collection of utility methods. 在这里,正如您的docstring所说,您有一组实用方法。 So why put them in a class? 那么为什么要把它们放在课堂上呢? Just make them top-level functions inside the logHelpers module (incidentally, Python style prefers lower_case_with_underscore for module names, so it should be "log_helpers.py"). 只需在logHelpers模块中创建顶级函数(顺便说一句,Python样式更喜欢使用lower_case_with_underscore作为模块名称,因此它应该是“log_helpers.py”)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM