Импорт переменных python программы после ее выполнения

Я написал два скрипта Python script1.py и script2.py. Я хочу запустить script1.py из script2.py и получить содержимое переменных script1, созданных во время выполнения script1. Script1 имеет несколько функций, в которых создаются переменные, в том числе и в main.

Спасибо за все ваши ответы. Я изучил ваши ответы, и, похоже, это не работает. Вот виновные сценарии, о которых я говорю:

script1.py

def main(argv):
    """Main of script 1
    Due to the  internal structure of the script this 
    main function must always be called with the flag -d
    and a corresponding argument.
    """
    global now
    now = datetime.datetime.now()

    global vroot_directory
    vroot_directory = commands.getoutput("pwd")

    global testcase_list_file
    testcase_list_file = 'no_argument'

    try:
        opts, args = getopt.getopt(argv, "d:t:", 
            ["directory_path=", "testcase_list="])
    except getopt.GetoptError, err:
        print command_syntax
        sys.exit()
    for opt, arg in opts:
        if opt in ("-d", "--directory"):
            vroot_directory = arg
        if opt in ("-t", "--testcase"):
             testcase_list_file = arg

    def function1():
        pass  

    def function2():
        if testcase_list_file == 'no_argument':
            function1()
        else:
            function2()

if __name__ == "__main__":
    main(sys.argv[1:]) 

script2.py

from Tkinter import *

class Application:
    def __init__(self):
        """ main window constructor """
        self.root = Tk()
        # I'd like to import here the variables of script1.py
        self.root.title(script1.vroot_directory)   ?
        self.root.mainloop()

# Main program
f = Application()

Извините за мои ошибки и спасибо за ваши уместные замечания. У меня есть следующее сообщение об ошибке:

" AttributeError: объект "модуль" не имеет атрибута "vroot_directory" "

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

from Tkinter import *
import script1

class Application:
    def __init__(self):
        """ main window constructor """
        self.root = Tk()
        script1.main(-d directory -t testcase_list_file) # to launch script1
        self.root.title(script1.vroot_directory)   # and after use its variables and functions
        self.root.mainloop()

# Main program
f = Application()

person Bruno    schedule 17.08.2010    source источник
comment
Я почистил ваш код; вы должны использовать хорошее форматирование при размещении его здесь. В чем ошибка? То, что вы написали, должно работать.   -  person Katriel    schedule 17.08.2010
comment
Если это полное содержимое script2.py, оно, конечно, не сработает — вы не включили import script1! Как я и несколько других сказали ниже.   -  person Katriel    schedule 17.08.2010
comment
Из вашего поста у меня сложилось впечатление, что вы хотите запустить script1, а затем когда-нибудь в будущем сможете запустить второй сценарий и по-прежнему получать значения, установленные в script1. Это правильно?   -  person g.d.d.c    schedule 17.08.2010
comment
Да, и скрипт1 должен запускаться из скрипта2. Нет импорта или команды (например, os.system), способной это сделать?   -  person Bruno    schedule 17.08.2010


Ответы (5)


Я думаю, что вы ищете какую-то форму постоянства объекта. Лично я использую для этого модуль полки:

Скрипт 1:

import shelve

def main(argv):
    """Main of script 1
    Due to the  internal structure of the script this 
    main function must always be called with the flag -d
    and a corresponding argument.
    """

    settings = shelve.open('mySettings')

    global now
    now = datetime.datetime.now()

    settings['vroot_directory'] = commands.getoutput("pwd")

    settings['testcase_list_file'] = 'no_argument'

    try:
        opts, args = getopt.getopt(argv, "d:t:", 
            ["directory_path=", "testcase_list="])
    except getopt.GetoptError, err:
        print command_syntax
        sys.exit()
    for opt, arg in opts:
        if opt in ("-d", "--directory"):
            settings['vroot_directory'] = arg
        if opt in ("-t", "--testcase"):
            settings['testcase_list_file'] = arg

    def function1():
        pass  

    def function2():
        if testcase_list_file == 'no_argument':
            function1()
        else:
            function2()

if __name__ == "__main__":
    main(sys.argv[1:]) 

Скрипт 2:

from Tkinter import *
import shelve

class Application:
    def __init__(self):
        settings = shelve.open('mySettings')

        """ main window constructor """
        self.root = Tk()
        # I'd like to import here the variables of script1.py
        self.root.title(settings['vroot_directory'])   ?
        self.root.mainloop()

# Main program
f = Application()

Модуль shelve использует модуль pickle в своей реализации, поэтому вы также можете посмотреть на модуль pickle для другого подхода.

person g.d.d.c    schedule 17.08.2010
comment
Спасибо ! Я собираюсь попробовать этот подход. - person Bruno; 17.08.2010
comment
Я пробовал это, но, к сожалению, это не работает, появляется следующее сообщение: keyError: 'vroot_directory' (у меня такое же сообщение, если я пытаюсь получить другую переменную, как сейчас) - person Bruno; 18.08.2010
comment
@Bruno - Если вы получаете ключевую ошибку, есть несколько возможных объяснений. Обе программы запускаются из одного каталога? Если вы проверите, откуда вы вызывали файлы и каталоги их контейнеров, вы найдете файл mySettings? Возможно, вам потребуется указать полный путь к shelve.open() в обоих сценариях, чтобы убедиться, что они выбирают один и тот же объект. - person g.d.d.c; 18.08.2010
comment
Спасибо за советы. Я просмотрел файл mySettings, и он находится в правильном каталоге. Я изменил пути на абсолютные пути, и результат тот же. Чтобы запустить программу, я пробовал в script2.py os.system( ./script.py -d directory -t testcase_list_file) (после выполнения chmod +x на script1.py), и я получил сообщение sh: script1. py: команда не найдена на терминале. с уважением, - person Bruno; 18.08.2010
comment
Моя ошибка: после очередной попытки все отлично работает! Большое спасибо gddc и всем за ваше время и помощь. с уважением, - person Bruno; 18.08.2010

От script2 делать

import script1

Это запустит любой код внутри script1; любые глобальные переменные будут доступны, например. script1.result_of_calculation. Вы можете установить глобальные переменные, как показано ниже.


сценарий1:

from time import sleep
def main( ):
    global result
    sleep( 1 ) # Big calculation here
    result = 3

сценарий2:

import script1
script1.main( ) # ...
script1.result # 3

Обратите внимание, что было бы лучше заставить main() в script1 возвращать result, чтобы вы могли

import script1
result = script1.main( )

Это лучше инкапсулирует поток данных и, как правило, более похоже на Python. Он также избегает глобальных переменных, что, как правило, плохо.

person Katriel    schedule 17.08.2010

Python — это интерпретируемый язык, поэтому, когда вы просто импортируете скрипт в другой скрипт (например, написав import script1 внутри script2), интерпретатор загрузит второй скрипт и выполнит его шаг за шагом. Каждое определение функции приведет к вызываемому функциональному объекту и так далее, и каждое выражение будет просто выполнено.

После этого вы можете получить доступ ко всему из модуля с помощью script1.globalvar1 и так далее.

person tux21b    schedule 17.08.2010
comment
действительно ли это поведение связано с тем, что python является интерпретируемым языком? (не риторический вопрос ;) - person Nicolas78; 17.08.2010
comment
Эта концепция, по крайней мере, не работает со связанным языком, потому что тогда в процессе связывания устанавливаются только некоторые ссылки, но никакие операторы не выполняются. В таком языке вам пришлось бы помещать все в функцию инициализации и вызывать ее вручную. - person tux21b; 17.08.2010

Есть две возможности: во-первых, объединить их в один скрипт. Это может выглядеть примерно так (в script2.py)

import script1

...
script1.dostuff()
importantvar = script1.importantvar
doScript2Stuff(importantvar)

Однако, не зная вашего приложения, я бы посоветовал инкапсулировать все, что делает script1, в функцию, чтобы вы могли просто вызвать

(var1, var2, var3) = script1.dostuffAndReturnVariables()

поскольку всегда полезно избегать глобальных переменных. Кроме того, это может оказаться удобным в дальнейшем, если вещи в script1 выполняются не в момент их импорта (как это делается, если вы пишете все команды непосредственно на главном уровне), а когда вы этого хотите, вызывая функция. В противном случае, как только вы получите больше модулей, все может запутаться, и вы можете изменить порядок команд импорта, потому что они делают так много всего.

Вторая возможность, если по какой-то причине их нужно запускать отдельно, — это использовать pickle.

Напишите

output = open(picklefile, "w")
pickle.dump(vars, output)    
output.close()

в script1.py

а потом

inputfile = open(picklefile, "r")
vars = pickle.load(inputfile)
input.close()

в script2.py. Таким образом, вы сохраняете содержимое вашего var в файл и можете восстановить его оттуда, когда это необходимо.

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

person Nicolas78    schedule 17.08.2010

В зависимости от того, сколько переменных вы хотите передать в script2.py, вы можете передать их через аргументы и получить в виде массива argv. Вы можете запустить script1.py, а затем из этого скрипта запустить os.system('script2.py arg0 arg1 arg2 arg3') для вызова script2.py.

Затем вы можете подобрать свои переменные в своем script2.py, выполнив следующие действия:

import sys

arg0 = sys.argv[0]
arg1 = sys.argv[1]
...
person Martin    schedule 17.08.2010
comment
-1 Вы не должны связываться между модулями Python с помощью командной строки. - person Katriel; 17.08.2010
comment
Конечно, это всего лишь предложение, возможно, это оказывается единственным способом в его обстоятельствах, которым он может достичь своей цели. - person Martin; 17.08.2010
comment
Что ж, ладно, но я не могу придумать обстоятельств, при которых вам пришлось бы это делать. pickle был бы лучшим способом передачи данных, если бы вы не могли сделать это во время выполнения. - person Katriel; 17.08.2010