Синхронизация переменных между программами при исполнении - PullRequest
0 голосов
/ 30 мая 2018

Я пытаюсь создать базовый модуль, который добавляет функцию execfile из Python 2. * в Python3 (используя функцию execf(a)).Модуль использует преимущества импорта для запуска файла .py, используя что-то вроде этого:

import fibonacci 
# From a fibonacci.py file

fibonacci.main()
# Running the program

Я использую это преимущество, используя функцию exec в нескольких случаях, чтобы прочитать имя файла и вставить его в тефункции и строки.

Вот как выглядит модуль (называемый execfile):

def execf(a):
  try:
    a.replace(".py", "") #removes '.py' from filename for use in exec functions
    exec('import {}'.format(a)) #imports the specified file
    exec('{}.main()'.format(a)) #runs the specified file
  except AttributeError:
    pass # Proceeds to rest of code after a sys.exit()
  except ModuleNotFoundError:
    pass # Proceeds to rest of code after program end

Это содержимое fibonacci.py:

def fibonacci(n):
    if n <= 1:
        return n
    else:
        return fibonacci(n-1) + fibonacci(n-2)

n = int(input("Enter number of terms:"))
print("Fibonacci sequence:")
for i in range(n):
    print(fibonacci(i))

Это main.py (исходный скрипт, который я выполняю):

from execfile import execf

execf('fibonacci.py')
print("That was " + a + " numbers of the Fibonacci sequence.")

Я хочу, чтобы переменная a из fibonacci.py была пригодна для использования в файле main.py, чтобы яможно распечатать, и это должно быть применимо для всех переменных в сценарии.Есть ли способ изменить глобальные переменные или выполнить функцию в глобальной области действия main.py, чтобы переменные можно было использовать в main.py после execf -ing файла?

Я думал одобавление в комментарий чего-либо, что можно было бы отсканировать и которое обнаружило бы переменные, которые необходимо добавить в глобальную областьЧто-то вроде:

# fibonacci.py

...

#-;- variables: {"foo": bar, "baz": boo} -;-



# execfile.py

variables = scan_for_variables(script)

Но я не смог найти ничего о том, как заставить Python «искать» эти переменные.Пожалуйста, дайте мне знать, если у вас есть какие-либо вопросы, спасибо!

1 Ответ

0 голосов
/ 30 мая 2018

То, что вы сделали, совсем не то же самое, что execfile.Поэтому неудивительно, что он не имеет такого же эффекта, как execfile.

  • execexecfile), выполняющий некоторый код непосредственно в текущей области.
  • import проверяет, загружен ли уже модуль, выполняет код в совершенно новой области, если нет, и затем выдает переменную, содержащую этот объект модуля в текущей области.

Например, допустим, у нас есть файл с именем mod.py, который выглядит следующим образом:

x = 1
print(x)

Теперь давайте import it:

>>> import mod
1
>>> mod.x
1
>>> x
NameError: name 'x' is not defined
>>> import mod # nothing will get printed the second and later times

Сравните, что происходиткогда вы execfile это:

>>> execfile('mod.py')
1
>>> mod.x
NameError: name 'mod' is not defined
>>> x
1
>>> execfile('mod.py')
1

Кроме того, ваш execf даже не работает по нескольким причинам:

  • a.replace(".py", "") не изменяет a, просто возвращает новую игнорируемую строку.
  • Ваш модуль fibonacci.py не имеет функции с именем main.
  • Вы не можете "перейти к остальной части кода после sys.exit", потому что sys.exit выходит из программы.Вы можете справиться с этим с помощью except SystemExit:, но не должны.Во всяком случае, вы определенно не можете справиться с этим except AttributeError:;он срабатывает только из-за того, что, например, модуль существует, но не имеет атрибута .main.

В любом случае, как Что нового в Python3.0 объясняет, что правильный способ сделать execfile в Python 3 - это open файл, read его содержимое и exec их.Другими словами:

with open(a) as f:
    exec(f.read())

Если вы хотите обернуть это в функцию, обратите внимание, что она выполнит код внутри локальной среды этой функции.Если вы хотите выполнить его в глобальных значениях, независимо от того, что, или в среде его вызывающей стороны, или чего-то еще, вам нужно указать это.См. exec документы для подробностей, но для простого примера:

def execf(a):
    with open(a) as f:
        exec(f.read(), globals())

В качестве примечания, в редком случае, когда вы действительно делаете нужно делать import динамически, вы не должны exec оператор import, вы должны использовать importlib.import_module:

try:
    mod = importlib.import_module(a)
except ImportError:
    # handle that problem
else:
    mod.main()
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...