2014-10-30 5 views
0

Я хотел бы знать, что лучше всего, когда вы хотите «вернуть» что-то из скрипта python.Python subprocess.Popen: sys.stdout vs .txt file vs Cpickle.dump

Вот моя проблема. Я запускаю Python childScript из родительского кода, используя метод subprocess.Popen. Я хотел бы получить кортеж двух поплавков от выполнения первого скрипта.

Теперь, первый метод я видел, используя sys.stdout и трубу в функции подпроцесса следующим образом:

child.py:

if __name__ == '__main__': 
    myTuple = (x,y) 
    sys.stdout.write(str(myTuple[0]) +":"+str(myTuple[1])) 
    sys.stdout.flush() 

parent.py:

p = subprocess.Popen([python, "child.py"], stdout=subprocess.PIPE) 
out, err = p.communicate() 

Хотя here он говорит, что не рекомендуется в большинстве случаев, но я не знаю, почему ...

Второй способ - написать мой кортеж в текстовый файл в Script1.py и открыть его в Script2.py. Но я думаю, что писать и читать файл занимает немного времени, поэтому я не знаю, лучше ли это делать?

Наконец, я мог бы использовать CPickle и сбросить свой кортеж и открыть его с script2.py. Я предполагаю, что это будет немного быстрее, чем использование текстового файла, но будет ли это лучше, чем использование sys.stdout?

Что было бы правильным способом?

--------------------------------------- EDIT ------ ------------------------------------------

Я забыл упомянуть что я не могу использовать импорт, поскольку parent.py фактически генерирует child.py в папке. Действительно, я делаю многопроцессорную обработку.

Parent.py создает 10 каталогов, в которых child.py копируется в каждом из них. Затем я запускаю каждый из child.py из parent.py на нескольких процессорах. И я хочу, чтобы parent.py собирал результаты, «возвращенные» всем child.py. Таким образом, parent.py не может импортировать child.py, поскольку он еще не создан, или, может быть, я могу сделать какой-то динамический импорт? Я не знаю ...

-------------------------------------- -EDIT2 -----------------------------------------------

Другое редактирование, чтобы ответить на вопрос относительно того, почему я продолжаю этот путь. Child.py на самом деле вызывает ironpython и другой скрипт для запуска сборки .NET. Причина, по которой я должен копировать все файлы child.py в определенных папках, состоит в том, что эта сборка генерирует файл ресурсов, который затем используется сам по себе. Если я не копирую child.py (и сборку кстати) в каждой подпапке, файлы ресурсов копируются в корневой каталог, который создает конфликты при вызове нескольких процессов с использованием модуля многопроцессорности. Если у вас есть предложения об этой общей архитектуре, то это более чем приветствуется :).

Благодаря

+0

неродственного: в общем, 'script1.py',' script2.py', 'float1',' float2' не являются хорошими именами. Вы можете использовать 'child.py',' parent.py' для скриптов, если на ум не приходит ничего конкретного, а 'numbers' или' x, y' для чисел. – jfs

+0

Хорошо, я редактирую/дополняю его прямо сейчас. Спасибо! – Serge

ответ

2

Обычные, вы должны использовать import other_module и вызвать различные функции:

import other_module 

x, y = other_module.some_function(param='z') 

Если вы можете запустить сценарий, вы также можете импортировать его.

Если вы хотите использовать subprocess.Popen(), то, чтобы передать пару поплавков, вы можете использовать формат json: он читается человеком, точным (в данном случае), и он читается машинами. Например:

child.py:

#!/usr/bin/env python 
import json 
import sys 

numbers = 1.2345, 1e-20 
json.dump(numbers, sys.stdout) 

parent.py:

#!/usr/bin/env python 
import json 
import sys 
from subprocess import check_output 

output = check_output([sys.executable, 'child.py']) 
x, y = json.loads(output.decode()) 

Child.py фактически вызывает IronPython и другой сценарий для запуска сборки .Net. Причина, по которой я должен копировать все файлы child.py, состоит в том, что эта сборка генерирует файл ресурсов, который затем используется им. Если я не копирую child.py в каждом подкаталоге, файлы ресурсов копируются в корневой каталог, который создает конфликты при вызове нескольких процессов с использованием модуля многопроцессорности. Если у вас есть предложения об этой общей архитектуре, то это более чем приветствуется :).

Вы можете поместить код из child.py в parent.py и вызвать os.chdir() (после развилки), чтобы выполнить каждый multiprocessing.Process в своем рабочем каталоге или использовать cwd параметр (он задает текущий рабочий каталог для подпроцесса) при запуске сборка с помощью subprocess модуля:

#!/usr/bin/env python 
import os 
import shutil 
import tempfile 
from multiprocessing import Pool 

def init(topdir='.'): 
    dir = tempfile.mkdtemp(dir=topdir) # parent is responsible for deleting it 
    os.chdir(dir) 

def child(n): 
    return os.getcwd(), n*n 

if __name__ == "__main__": 
    pool = Pool(initializer=init) 
    results = pool.map(child, [1,2,3]) 
    pool.close() 
    pool.join() 
    for dirname, _ in results: 
     try: 
      shutil.rmtree(dirname) 
     except EnvironmentError: 
      pass # ignore errors 
+0

Я забыл упомянуть, что я не могу использовать импорт, так как script2 фактически создает скрипт1 в папке. Действительно, я делаю многопроцессорную обработку. Script2 создает 10 каталогов, где script1 копируется в каждом из них. Затем я запускаю каждый скрипт1 из сценария2. И я хочу, чтобы скрипт2 собирал результаты, «возвращенные» всем скриптом1. Так что script2 не может импортировать скрипт1, поскольку он еще не создан, или, может быть, я могу сделать какой-то динамический импорт? Я не знаю. Но я посмотрю на json. Благодаря! – Serge

+1

@ user2390615: 1. любая дополнительная информация должна идти на ваш вопрос вместо комментария, чтобы другие могли легко найти его. 2. Если сценарий еще не сгенерирован, вы не сможете его запустить с помощью подпроцесса. :) Если файл уже существует, вы можете его импортировать (переместите код верхнего уровня в функцию, чтобы избежать его при импорте). 3. Создание сценариев «на лету» и их копирование не похоже на хороший дизайн - вы должны более внимательно изучить его. – jfs

+0

Я отредактировал вопрос. Благодарю. – Serge