2014-11-06 2 views
4

(Есть много похожих и более общих вопросов, которые пытаются решить их после прочтения через них, не могут заставить их работать, поэтому задайте здесь более конкретную версию из того, что я вижу)Python: глобальная переменная не определена на уровне модуля

Я думаю, что я действительно не понимаю, как Python делает ООП из-за моего более C#/C++ фона. Итак, вот что я пытаюсь сделать в этот момент.

Я начинаю с двух модулей, чтобы настроить остальную часть моего проекта, частично как проверку на работоспособность и доказательство концепции. Один модуль записывает файлы в файл, когда я ухожу, одновременно сохраняя данные из нескольких модулей (чтобы, в конечном итоге, упаковать их все и выгрузить их по запросу). Все это в 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 \ есть пустой инициализации .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, что различные отчеты, кажется, показывают, что означает, что 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 здесь?)

[EDIT] На основе обратной связи попыталась мини версии, которая полностью устранена внутренние классы: Ok, так что сделала местную мини-класс на основе того, что вы сказали:

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

Установите его с помощью init.ру

__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

Так еще в квадрате один :((и все еще нужно для хранения состояния)

[EDIT] Добавление 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, я получил его работу с мини-ручкой. Я не знаю, почему другой подход/подходы не работал, но это, похоже, исправить. (Ресурсы: 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» - для второго файла для вызова помощника.

Спасибо Даниэлю Роземан за помощь и предложения, они заставили меня взглянуть немного в правильном направлении. Если вы можете понять, почему предыдущие вещи не работали, было бы очень полезно просто добавить к моему пониманию этот язык, но я собираюсь идти дальше и отмечать ваш ответ как «Ответ», поскольку у него была очень полезная обратная связь.

ответ

9

Прежде чем начать, обратите внимание, что предупреждения PyCharm не являются действительными ошибками Python: если вы запустили свой код, вы, вероятно, получите более полезную обратную связь (помните, что статический анализ динамического языка, такого как Python, может доставить вам до сих пор, многие вещи не могут быть решены, пока вы фактически не запустите код).

Во-первых, действительно непонятно, почему у вас есть вложенные классы здесь. Внешний класс кажется совершенно бесполезным; вы должны удалить его.

Причина сообщения об ошибке «self» заключается в том, что вы определили метод экземпляра, который может быть вызван только в экземпляре log. Вы можете сделать mylogger (абсолютно без необходимости префикса с двойным подчеркиванием) экземпляр: mylogger = log() - а затем импортировать это или импортировать класс и создать экземпляр, где он используется.

Итак, в вашем первом фрагменте сообщение об ошибке достаточно ясно: вы не определили mylogger. Используя мою рекомендацию выше, вы можете сделать from helpers import mylogger, а затем позвонить по телефону mylogger.classEnter().

И наконец, я не вижу, что это делает global заявление в someFunction. Нет необходимости объявлять имя глобальным, если вы не планируете переназначить его в своей области действия и не имеете такое переназначение, отраженное в глобальной области. Вы этого не делаете, поэтому нет необходимости в global.

Кстати, вы также должны задать вопрос, нужен ли вам даже внутренний класс log. Вообще говоря, классы полезны только тогда, когда вам нужно сохранить какое-то состояние в объекте.Здесь, как говорит ваш документ, у вас есть набор полезных методов. Так зачем ставить их в класс? Просто сделайте их функциями верхнего уровня внутри модуля logHelpers (кстати, стиль Python предпочитает lower_case_with_underscore для имен модулей, поэтому он должен быть «log_helpers.py»).

+0

Большое вам спасибо за отзыв - я попробую это как можно скорее (как только я снова получу код позже сегодня) Я занимаюсь вложенными классами, потому что мне нужна единственная точка контакта, откуда я могу расширяются в разные функциональные возможности, которые связаны, но служат для разных целей. (простое ведение журнала, утверждает сейчас, более позднее). Я мог бы сделать то же самое, имея разные классы и один класс с несколькими переменными, каждый из которых хранит один класс, просто пытался сохранить внутренние определения, поскольку классы не должны реализовываться отдельно/сохранять автоматически заполненную. –

+0

И еще - эти дополнительные __ были опечатываются здесь, когда я пытался воспроизвести различные вещи, которые я пробовал, удалил их. –

+0

Хорошо, помните, что вложение класса не дает внутреннему классу никакого привилегированного доступа к внешнему классу, поэтому он редко имеет какие-либо преимущества. Обычно в Python элементами вложенности являются пакеты и модули, а не классы. –

Смежные вопросы