2017-01-13 8 views
1

Немного предыстории проблемы. Я пишу код в Python2.7, который работает нормально. Но я решил разбить его на модули для удобства использования и обслуживания, что является новым для меня, поэтому возникают некоторые проблемы. Хотя я смог заставить его работать с помощью метода хитов и пробных версий, но не уверен, что это правильный подход или нет, поэтому он делится здесь. Общий код здесь - это упрощенная репликация реального кода, управляющего той же логикой, порядком и подходом.В Python2.7 как использовать переменные из основного скрипта и других пользовательских функций

MainEx.py это скрипт работает на самом высоком уровне

from LogIn_1 import LogIn 
global NumTry 
NumTry = 2 
LogIn() 
# xx is here just to show NumTry variable is further used in MainEx script 
xx = NumTry*3 

В основном то, что я трудный общаться здесь переменная NumTry используется в MainEx.py (скрипт на самом высоком уровне), а также внутри LogIn(). И также будут использоваться другими функциями, которые я создаю.

LogIn_1.py является определенной пользователем функции

def LogIn(): 
    from MainEx import NumTry 
    # following are some computations involving NumTry 
    print NumTry 

Запуск MainEx.py дает результат:

2 
2 

Вопросы: 1. Не знаю, почему она приносит результат в два раза 2. кажется нечетным, MainEx импортирует LogIn_1 и LogIn_1, импортируя MainEx. Вид ситуации пинг-понга, импортирующей переменные друг от друга.

Я могу правый исход со следующими изменениями: MainEx.py

from LogIn_1 import LogIn 
global NumTry 
NumTry = 2 
#LogIn() 
# xx is here just to show NumTry variable is further used in MainEx script 
xx = NumTry*3 

LogIn_1.py

def LogIn(): 
    from MainEx import NumTry 
    # following are some computations involving NumTry 
    print NumTry 
LogIn() 

Запуск MainEx.py дает результат:

2 

I я пытаюсь понять лучшие практики, чтобы избежать будущих проблем.

ответ

1

Если добавить кучу заявлений для печати в код, вы можете следить за окровавленные детали:

# MainEx.py 
print 'MainEx: start' 
from LogIn_1 import LogIn 
print 'MainEx: after Login import' 
global NumTry 
NumTry = 2 
print 'MainEx: before Login() call' 
LogIn() 
print 'MainEx: after Login() call' 
xx = NumTry*3 
print 'MainEx: finish' 

# LogIn_1.py 
print 'start LogIn_1' 
def LogIn(): 
    print ' Login(): start' 
    from MainEx import NumTry 
    print ' Login(): after MainEx import' 
    print NumTry 
    print ' Login(): finish' 
print 'finish LogIn_1' 

Выходные:

MainEx: start 
start LogIn_1 
finish LogIn_1 
MainEx: after Login import 
MainEx: before Login() call 
    Login(): start 
MainEx: start      # Code in MainEx running again! 
MainEx: after Login import 
MainEx: before Login() call 
    Login(): start 
    Login(): after MainEx import 
2 
    Login(): finish 
MainEx: after Login() call 
MainEx: finish 
    Login(): after MainEx import 
2 
    Login(): finish 
MainEx: after Login() call 
MainEx: finish 

Как вы можете видеть, сочетающий в себе (а) круговой импорт с (b) кодом, имеющим побочные эффекты верхнего уровня, приводит к порочным результатам. В частности, когда from MainEx import NumTry работает в вызове Login(), кажется, что Python должен повторно выполнить код в MainEx, так как этот модуль еще не имеет атрибута NumTry, что приводит к двойной печати. Я не ожидал такого результата ... но вот оно.

предложения Лучшие практики:

  • Помещенный ваши операторы импорта в верхней части ваших модулей, а не внутри функций или классов.

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

  • Создайте свои модули так, чтобы ничего не произошло на своих верхних уровнях. Модули должны делать не что иное, как определять классы, определять функции, назначать константы или импортировать модули нижнего уровня. Только первичный модуль вашей системы должен делать что-то - и что-то должно быть, чтобы вызвать вашу функцию верхнего уровня (проходящее в любой командной строки арг), и даже, что вызов должен быть условным, так как в общих чертах здесь:

    import sys 
    
    def main(args): 
        ... 
    
    def foo(): 
        ... 
    
    def bar(): 
        ... 
    
    if __name__ == '__main__': 
        main(sys.argv[1:]) 
    
+0

спасибо @FMc, хотя я прибегал к одной большой программе, но это полезно и будет продолжать изучать модульный подход – Abacus