एक संशोधित वातावरण के साथ पायथन सबप्रोसेस / पोपेन


285

मेरा मानना ​​है कि थोड़ा संशोधित वातावरण के साथ एक बाहरी कमांड चलाना एक बहुत ही सामान्य मामला है। मैं इसे कैसे करूं:

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

मुझे लग रहा है कि एक बेहतर तरीका है; क्या यह ठीक लग रहा है?


10
os.pathsepप्लेटफार्मों पर काम करने वाले रास्तों के लिए ":" के बजाय उपयोग करना पसंद करते हैं । देखें stackoverflow.com/questions/1499019/…
amit

8
@phaedrus मुझे यकीन नहीं है कि जब वह पथों का उपयोग कर रहा है तो यह बहुत प्रासंगिक नहीं है /usr/sbin:-)
दिमित्री गिंजबर्ग

जवाबों:


405

मुझे लगता 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)

>>> env = os.environ.copy >>> env ['foo'] = 'बार' Traceback (सबसे हालिया कॉल अंतिम): फ़ाइल "<stdin>", पंक्ति 1, में <मॉड्यूल> TypeError: 'instmethod' वस्तु आइटम असाइनमेंट का समर्थन नहीं करता है
उपयोगकर्ता 1338062

5
@ user1338062 आप चर os.environ.copyको वास्तविक विधि प्रदान कर रहे envहैं, लेकिन आपको विधि os.environ.copy()को कॉल करने के परिणाम को निर्दिष्ट करने की आवश्यकता है env
chown

4
पर्यावरण चर संकल्प केवल वास्तव में काम करता है यदि आप shell=Trueअपने subprocess.Popenमंगलाचरण में उपयोग करते हैं । ध्यान दें कि ऐसा करने के संभावित सुरक्षा निहितार्थ हैं।
डेनियलपॉप्स

सबप्रोसेस के अंदर। पोपेन (my_command, env = my_env) - "my_command" क्या है
avinash

@ अविनाश - my_commandबस चलाने की आज्ञा है। यह उदाहरण /path/to/your/own/programया किसी अन्य "निष्पादन योग्य" कथन के लिए हो सकता है ।
kajakIYD

64

यह इस बात पर निर्भर करता है कि मुद्दा क्या है। यदि यह क्लोन और पर्यावरण को संशोधित करने के लिए एक समाधान हो सकता है:

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

लेकिन यह कुछ हद तक इस बात पर निर्भर करता है कि बदले हुए चर मान्य पायथन पहचानकर्ता हैं, जो कि वे अक्सर होते हैं (आप कितनी बार पर्यावरण चर नामों में चलते हैं जो अल्फ़ान्यूमेरिक + अंडरस्कोर या चर नहीं हैं जो एक संख्या से शुरू होते हैं?)।

अन्यथा आप कुछ इस तरह लिख सकते हैं:

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

बहुत ही विषम स्थिति में (आप पर्यावरण चर नामों में नियंत्रण कोड या गैर-एएससीआई वर्ण का उपयोग कितनी बार करते हैं?) कि पर्यावरण की कुंजी bytesआप (python3 पर) भी उस निर्माण का उपयोग नहीं कर सकते हैं।

जैसा कि आप देख सकते हैं कि तकनीक (विशेष रूप से पहली) का उपयोग यहां पर्यावरण की कुंजी पर लाभ देता है सामान्य रूप से मान्य अजगर पहचानकर्ता है, और अग्रिम में (कोडिंग समय पर) भी जाना जाता है, दूसरे दृष्टिकोण में समस्याएं हैं। ऐसे मामलों में जहां ऐसा नहीं है, आपको संभवतः दूसरे दृष्टिकोण की तलाश करनी चाहिए ।


3
वोट दें। मुझे नहीं पता था कि आप लिख सकते हैं dict(mapping, **kwargs)। मैंने सोचा कि यह या तो था। नोट: यह @Daniel Burke केos.environ रूप में इसे संशोधित किए बिना प्रतियों में वर्तमान में स्वीकृत उत्तर में सुझाव दिया गया है लेकिन आपका उत्तर अधिक रसीला है। पायथन 3.5+ में भी आप कर सकते हैं dict(**{'x': 1}, y=2, **{'z': 3})पेप 448 देखें ।
JFS

1
यह उत्तर कुछ बेहतर तरीके बताता है (और यह तरीका इतना बढ़िया क्यों नहीं है) दो शब्दकोशों को एक नए में मिलाने के लिए: stackoverflow.com/a/26853961/27729
krupan

@ क्रंदन: आप इस विशिष्ट उपयोग के मामले में क्या नुकसान देखते हैं ? (मनमाना dicts विलय और कॉपी / अद्यतन environ अलग कार्य हैं)।
JFS

1
@ सर्वप्रथम सामान्य मामला यह है कि पर्यावरण चर मान्य अजगर पहचानकर्ता होगा, जिसका अर्थ है पहला निर्माण। उस स्थिति के लिए आपकी कोई भी आपत्ति नहीं है। दूसरे मामले में आपकी मुख्य आपत्ति अभी भी विफल है: गैर-स्ट्रिंग कुंजी के बारे में बात इस मामले में लागू नहीं होती है क्योंकि कुंजी को मूल रूप से वैसे भी वातावरण में तार होना आवश्यक है।
skyking

@JFSebastian आप सही हैं कि इस विशिष्ट मामले के लिए यह तकनीक ठीक है और मुझे खुद को बेहतर तरीके से समझाना चाहिए था। मैं क्षमाप्रार्थी हूं। मैं सिर्फ उन लोगों (जैसे अपने आप) की मदद करना चाहता था, जो शायद इस तकनीक को लेने के लिए लुभाए गए थे और इसे दो मनमाने ढंग से शब्दकोशों को विलय करने के सामान्य मामले में लागू कर सकते हैं (जिसमें कुछ गेटेका है, जैसा कि उत्तर मैंने बताया है)।
क्रुपण

24

आप उपयोग कर सकते हैं my_env.get("PATH", '')के बजाय my_env["PATH"]मामले में PATHकिसी भी तरह मूल वातावरण में परिभाषित नहीं किया है, लेकिन अन्य की तुलना में है कि यह ठीक लग रहा है।


21

पायथन 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}

@avinash, subprocess.Popen प्रलेखन देखें। यह "कार्यक्रम के तर्कों का एक क्रम है या फिर एक एकल स्ट्रिंग"।
skovorodkin

10

Os.envrion ऑब्जेक्ट आदि की प्रतिलिपि बनाए बिना अस्थायी रूप से एक पर्यावरण चर सेट करने के लिए, मैं यह करता हूं:

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

4

Env पैरामीटर एक शब्दकोश स्वीकार करता है। आप बस os.environ को ले सकते हैं, एक कुंजी (अपने इच्छित चर) (जो आपको चाहिए, तो उस हुकुम की एक प्रति में) जोड़ें और इसे एक पैरामीटर के रूप में उपयोग करें Popen


यह सबसे सरल उत्तर है यदि आप एक नया परिवेश चर जोड़ना चाहते हैं। os.environ['SOMEVAR'] = 'SOMEVAL'
एंडी फ्रेली

1

मुझे पता है कि इसका उत्तर कुछ समय के लिए दिया गया है, लेकिन कुछ बिंदु हैं जो कुछ लोग अपने पर्यावरण चर में PATH के बजाय PYTHONPATH का उपयोग करने के बारे में जानना चाह सकते हैं। मैंने क्रोनॉजर्स के साथ अजगर लिपियों को चलाने की एक व्याख्या की है जो एक अलग तरीके से संशोधित पर्यावरण से संबंधित है ( यहां पाया गया )। सोचा कि यह उन लोगों के लिए कुछ अच्छा होगा, जिन्हें मेरी तरह, इस जवाब के लिए बस कुछ और चाहिए था।


0

कुछ परिस्थितियों में आप केवल पर्यावरण को अपनी उपप्रकारों की जरूरतों को पूरा करना चाहते हैं, लेकिन मुझे लगता है कि आपको सामान्य रूप से सही विचार मिल गया है (यही कारण है कि मैं इसे भी करता हूं)।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.