كيفية الحصول على البيئة من عملية فرعية؟
-
06-07-2019 - |
سؤال
أرغب في استدعاء عملية عبر برنامج بايثون، لكن هذه العملية تحتاج إلى بعض متغيرات البيئة المحددة التي يتم تعيينها بواسطة عملية أخرى.كيف يمكنني الحصول على متغيرات بيئة العملية الأولى لتمريرها إلى الثانية؟
وهذا هو شكل البرنامج:
import subprocess
subprocess.call(['proc1']) # this set env. variables for proc2
subprocess.call(['proc2']) # this must have env. variables set by proc1 to work
لكن عملية التنفيذ لا تشترك في نفس البيئة.لاحظ أن هذه البرامج ليست ملكي (الأول هو ملف .bat كبير وقبيح والثاني برنامج خاص) لذلك لا أستطيع تعديلهما (حسنًا، يمكنني استخراج كل ما أحتاجه من .bat لكنه مرهق للغاية ).
ملحوظة:أنا أستخدم نظام التشغيل Windows، ولكني أفضل الحل عبر الأنظمة الأساسية (لكن مشكلتي لن تحدث على أنظمة تشبه Unix ...)
المحلول
ومنذ كنت على ما يبدو في ويندوز، تحتاج إجابة ويندوز.
وإنشاء ملف دفعي المجمع، على سبيل المثال. "run_program.bat"، وتشغيل كل البرامج:
@echo off
call proc1.bat
proc2
وسيتم تشغيل البرنامج النصي وتعيين متغيرات بيئتها. تشغيل كل البرامج النصية في نفس مترجم (مثيل CMD.EXE)، وبالتالي فإن المتغيرات prog1.bat مجموعات <م> سوف م> يتم تعيين عند تنفيذ prog2.
وليس جميلة بشكل رهيب، لكنه سوف يعمل.
و(الناس يونكس، يمكنك أن تفعل الشيء نفسه في السيناريو باش: "file.sh المصدر")
نصائح أخرى
وهنا مثال على كيف يمكنك استخراج متغيرات البيئة من ملف دفعي أو كمد دون خلق النصي المجمع. التمتع بها.
from __future__ import print_function
import sys
import subprocess
import itertools
def validate_pair(ob):
try:
if not (len(ob) == 2):
print("Unexpected result:", ob, file=sys.stderr)
raise ValueError
except:
return False
return True
def consume(iter):
try:
while True: next(iter)
except StopIteration:
pass
def get_environment_from_batch_command(env_cmd, initial=None):
"""
Take a command (either a single command or list of arguments)
and return the environment created after running that command.
Note that if the command must be a batch file or .cmd file, or the
changes to the environment will not be captured.
If initial is supplied, it is used as the initial environment passed
to the child process.
"""
if not isinstance(env_cmd, (list, tuple)):
env_cmd = [env_cmd]
# construct the command that will alter the environment
env_cmd = subprocess.list2cmdline(env_cmd)
# create a tag so we can tell in the output when the proc is done
tag = 'Done running command'
# construct a cmd.exe command to do accomplish this
cmd = 'cmd.exe /s /c "{env_cmd} && echo "{tag}" && set"'.format(**vars())
# launch the process
proc = subprocess.Popen(cmd, stdout=subprocess.PIPE, env=initial)
# parse the output sent to stdout
lines = proc.stdout
# consume whatever output occurs until the tag is reached
consume(itertools.takewhile(lambda l: tag not in l, lines))
# define a way to handle each KEY=VALUE line
handle_line = lambda l: l.rstrip().split('=',1)
# parse key/values into pairs
pairs = map(handle_line, lines)
# make sure the pairs are valid
valid_pairs = filter(validate_pair, pairs)
# construct a dictionary of the pairs
result = dict(valid_pairs)
# let the process finish
proc.communicate()
return result
ومن أجل الإجابة على سؤالك، هل إنشاء ملف .py أن يفعل ما يلي:
env = get_environment_from_batch_command('proc1')
subprocess.Popen('proc2', env=env)
كما قلت، العمليات لا تشارك البيئة - لذا فإن ما تطلبه حرفيًا غير ممكن، ليس فقط في بايثون، ولكن مع أي لغة برمجة.
ما لك يستطيع ما تفعله هو وضع متغيرات البيئة في ملف، أو في أنبوب، وإما
- اطلب من العملية الأم قراءتها وتمريرها إلى proc2 قبل إنشاء proc2، أو
- اطلب من proc2 قراءتها وتعيينها محليًا
وهذا الأخير يتطلب التعاون من proc2؛يتطلب الأول أن تصبح المتغيرات معروفة قبل بدء تشغيل proc2.
وشيئين يتبادر إلى الذهن: (1) جعل العمليات تشترك في نفس البيئة، من خلال الجمع بينهما على نحو ما في نفس العملية، أو (2) لديها انتاج المنتجات العملية الأولى التي تحتوي على متغيرات البيئة ذات الصلة، وبهذه الطريقة بيثون يمكن قراءتها وبناء بيئة للعملية الثانية. أعتقد (على الرغم من أنني لست متأكدا 100٪) أنه لا يوجد أي طريقة للحصول على البيئة من فرعي أو جانبي كما كنت على أمل القيام به.
وبايثون القياسية وحدة المعالجة المتعددة يكون هناك نظام قوائم الانتظار التي تسمح لك لتمرير المخلل الكائن، قادرة على أن تنتقل عن طريق العمليات. أيضا العمليات يمكن تبادل الرسائل (كائن مخلل) باستخدام os.pipe. تذكر أن الموارد (على سبيل المثال: اتصال قاعدة البيانات) والتعامل معها. (على سبيل المثال: مؤشرات الملفات) لا يمكن مخلل
وأنت قد تجد هذا الرابط للاهتمام: الاتصالات بين العمليات مع متعدد المعالجة
وأيضا PyMOTw حول متعدد المعالجة الجدير بالذكر: أساسيات المعالجة المتعددة
وآسف لبلدي هجاء
ويورث البيئة من عملية الأصل. تعيين البيئة التي تحتاج إليها في النص الرئيسي، وليس فرعي أو جانبي (طفل).