سؤال

أعتقد أن تشغيل أمر خارجي مع بيئة معدلة قليلا هو حالة شائعة للغاية. هذه هي الطريقة التي أميل إليها للقيام بذلك:

import subprocess, os
my_env = os.environ
my_env["PATH"] = "/usr/sbin:/sbin:" + my_env["PATH"]
subprocess.Popen(my_command, env=my_env)

لقد شعرت بأذى أن هناك طريقة أفضل؛ هل تبدو بخير؟

هل كانت مفيدة؟

المحلول

أظن os.environ.copy() هو أفضل إذا كنت لا تنوي تعديل OS.Environ للعملية الحالية:

import subprocess, os
my_env = os.environ.copy()
my_env["PATH"] = "/usr/sbin:/sbin:" + my_env["PATH"]
subprocess.Popen(my_command, env=my_env)

نصائح أخرى

هذا يعتمد على ما هي المشكلة. إذا كان ذلك لاستنساخ وتعديل البيئة يمكن أن يكون حل واحد:

subprocess.Popen(my_command, env=dict(os.environ, PATH="path"))

ولكن هذا يعتمد إلى حد ما على أن المتغيرات التي تم استبدالها هي معرفات Python صالحة، والتي غالبا ما تكون في أغلب الأحيان (كم مرة تعمل بأسماء متغيرة للبيئة غير أبجدي رقمي + متغيرات أو متغيرات تبدأ برقم؟).

وإلا فسوف تستطيع كتابة شيء مثل:

subprocess.Popen(my_command, env=dict(os.environ, 
                                      **{"Not valid python name":"value"}))

في حالة غريبة للغاية (كم مرة تستخدم رموز التحكم أو أحرف غير ASCII في أسماء متغير البيئة؟) أن مفاتيح البيئة هي bytes لا يمكنك (على Python3) حتى استخدام هذا البناء.

كما ترون أن تقنيات (خاصة الأولى) المستخدمة هنا فوائد على مفاتيح البيئة عادة ما تكون معرفات بيثون صالحة، ومعروف أيضا مقدما (في وقت الترميز)، فإن النهج الثاني له مشاكل. في الحالات التي ليس فيها الأمر كذلك، يجب أن تبحث عنه مقاربة أخرى.

قد تستخدم my_env.get("PATH", '') بدلا من my_env["PATH"] في حال PATH غير محددة بطريقة ما في البيئة الأصلية، ولكن بخلاف ذلك يبدو جيدا.

مع بيثون 3.5 يمكنك القيام بذلك بهذه الطريقة:

import os
import subprocess

my_env = {**os.environ, 'PATH': '/usr/sbin:/sbin:' + os.environ['PATH']}

subprocess.Popen(my_command, env=my_env)

هنا في نهاية المطاف مع نسخة من os.environ وتجاوزت PATH القيمة.

كان ذلك ممكنا من قبل بيب 448. (تعميمات تفريغ إضافية).

مثال آخر. إذا كان لديك بيئة افتراضية (أي os.environ)، ومؤدي تريد تجاوز الإعدادات الافتراضية مع، يمكنك التعبير عنها مثل هذا:

my_env = {**os.environ, **dict_with_env_variables}

لتعيين متغير بيئة مؤقتا دون الحاجة إلى نسخ كائن OS.Envrion إلخ، أفعل هذا:

process = subprocess.Popen(['env', 'RSYNC_PASSWORD=foobar', 'rsync', \
'rsync://username@foobar.com::'], stdout=subprocess.PIPE)

تقبل المعلمة ENV القاموس. يمكنك ببساطة أخذ OS.Environ، إضافة مفتاح (المتغير المرغوب الخاص بك) (إلى نسخة من DICT إذا كان يجب) ذلك واستخدامه كمعلمة ل Popen.

أعلم أن هذا قد تم الرد عليه لبعض الوقت، ولكن هناك بعض النقاط قد يرغب البعض في معرفة استخدام PythonPath بدلا من المسار في متغير البيئة. لقد أوجزت شرحا لتشغيل البرامج النصية لبثون مع Cronjobs التي تتعامل مع البيئة المعدلة بطريقة مختلفة (وجدت هنا). يعتقد أنه سيكون من بعض الخير لأولئك الذين، مثلي، بحاجة فقط إلى أكثر قليلا من هذه الإجابة المقدمة.

في ظروف معينة، قد ترغب في نقل البيئة فقط لاحتياجاتك الفرعية، لكنني أعتقد أنك قد حصلت على الفكرة الصحيحة بشكل عام (فهذه الطريقة التي أفعلها أيضا).

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top