Python, verander huidige shell omgevingsvariabelen tijdens het gebruik van Popen?

Ik heb een xml die informatie over omgevingsvariabelen bevat om in te stellen in de shell door mijn python-script. Hier is een fragment van de XML:

/homeqt/libs.qt4/qt4.5.1
which make

Dit deel van dit fragment vertelt mijn python-script om omgevingsvariabelen QTDIR en MAKE in te stellen.

Mijn zorg is het verschil hoe ik de bovenstaande variabelen moet instellen. Ik weet dat ik os.environ kan gebruiken om omgevingsvariabelen in te stellen en zoiets als dit te doen:

os.environ['QTDIR'] = "/homeqt/libs.qt4/qt4.5.1"

Maar ik kan dit niet gebruiken om mijn MAKE-variabele in te stellen, ik moet de opdracht " die " uitvoert (om het pad van make executable te krijgen) uitvoeren. Mijn doel is om dezelfde methode/functie te gebruiken om alle variabelen in te stellen.

DUS, ik dacht om zoiets te doen:

Popen("QTDIR=/homeqt/libs.qt4/qt4.5.1 ; export QTDIR", shell=True, stdout=PIPE, stderr=PIPE)
Popen("MAKE=which make ; export MAKE", shell=True, stdout=PIPE, stderr=PIPE)

Maar als ik dit doe, wordt de variabele alleen ingesteld voor het subproces, niet voor de huidige shell.

Dus mijn vraag is, is er een manier om te doen wat ik wil? Ik wil de xml NIET analyseren en zoiets als dit doen:

(Pseudocode)

if QTDIR has normal value
    os.environ['QTDIR'] = "/homeqt/libs.qt4/qt4.5.1"
if MAKE has value to be executed
    p = Popen("which make", shell=True, stdout=PIPE, stderr=PIPE)
    stdout, stderr = p.communicate()
    os.environ['MAKE'] = stdout
1
We hebben vrij complexe bash-shellscripts met tonnen van als dan anders om onze producten te bouwen. Ik wil zo veel mogelijk informatie binnen de xml verplaatsen en het Python-script gewoon taken laten oproepen die eruit zijn gehaald. Ik wil het Python-script zo eenvoudig mogelijk maken. Dat is de reden. Dus, is het mogelijk?
toegevoegd de auteur peterphonic, de bron
Ja, zoiets als dit =) Ik denk dat de onderstaande oplossing logischer is ...
toegevoegd de auteur peterphonic, de bron
Waarom wil je niet?
toegevoegd de auteur Amber, de bron
@peterphonic Dus, wilt u een aantal waarden die speciaal moeten worden afgehandeld, maar u bent niet bereid om ze speciaal ergens te behandelen?
toegevoegd de auteur millimoose, de bron

2 antwoord

Ik zou gebruik maken van XML-attributen.

which make
/homeqt/libs.qt4/qt4.5.1

pseudocode, afhankelijk van uw XML-bibliotheek:

if node.attributes['type'] == 'command':
    value = os.popen(node.firstChild.text).read()
elif node.attributes['type'] == 'string':
    value = node.firstChild.text
os.environ[node.attributes['name']] = value
3
toegevoegd
@stefan: os.popen (). read() maakt geen onderscheid tussen een fout en een lege uitvoer.
toegevoegd de auteur jfs, de bron
Goed antwoord! Beter nog, upgrade naar de subprocess.check_output() standaardbibliotheekmethode die Nick Coghlan heeft bepleit vanwege zijn betere ontwerp.
toegevoegd de auteur Brandon Rhodes, de bron
Geef shell = True door aan de functie: check_output (opdracht, shell = True)
toegevoegd de auteur Brandon Rhodes, de bron
Inderdaad - overweeg een bug in te dienen zodat ze de docstring kunnen bijwerken om overeen te komen met het geweldige werk dat Nick heeft gedaan in de documentatie van de standaardbibliotheek, waar hij zowel de gemaksvraag als check_output() naar de top heeft verplaatst , en ook duidelijk gemaakt dat ze argumenten zoals shell gebruiken: docs.python .org/bibliotheek/subprocess.html
toegevoegd de auteur Brandon Rhodes, de bron
Ik heb hier gewoon wat geknoeid en ik ben het ermee eens dat dit voor sommige situaties een betere oplossing is, maar waarschijnlijk niet deze. Dit zou vereisen dat je de opdracht zelf analyseert, omdat check_output een array van argumenten bevat, dus je moet misschien iets proberen als check_output (command.split ('')), wat gewoon slecht nieuws is en niet het goede doet ding in bijna alle gevallen (wat als ik strings, ontsnapte spaties of puntkomma's zonder spaties naast elkaar heb genoteerd?) Het is beter om het door te geven aan de grammatica-parser van de shell.
toegevoegd de auteur stefan, de bron
Ah. Dit argument is niet gedocumenteerd in de helppagina :(
toegevoegd de auteur stefan, de bron

Uw weergave is dubbelzinnig:

/homeqt/libs.qt4/qt4.5.1
which make

Hoe kiest u tussen MAKE = welke of MAKE = `which make` maken:

$ a=which make ; echo $a
make: *** No targets specified and no makefile found.  Stop.

$ a=`which make` ; echo $a
/usr/bin/make

$ a='which make' ; echo $a
which make

Als het XML-bestand door de machine wordt gegenereerd en mensen dit bestand niet vaak bekijken/bewerken, kunt u een uitgebreide expliciete notatie gebruiken, zoals voorgesteld door @stefan .

Anders zou een meer beknopte en eenvoudige weergave kunnen worden gebruikt:

QTDIR: /homeqt/libs.qt4/qt4.5.1
$MAKE: which make

Hier is een Python-script dat die indeling in een woordenboek parseert:

for line in file:
    name, sep, value = map(str.strip, line.partition(':'))
    if sep: # ':' is in the line           
       if name.startswith('$'):
          name = name[1:] # strip '$'
          value = subprocess.check_output(value, shell=True).strip()
       d[name] = value

Of u kunt bijvoorbeeld:

d = yaml.load(file) # yaml is as complex as xml, but less explicit i.e., worse
# and transform keys that start with '$' here

xml-indeling kan een gerechtvaardigde terugval zijn als je meer complexe mogelijkheden nodig hebt.

0
toegevoegd
Eigenlijk denk ik dat xml een betere oplossing is. Het bevat niet alleen informatie over variabelen, maar ook taken die moeten worden uitgevoerd: cd $ MAINPATH; mkdir -p $ TARGET; cd "$ MAINPATH/$ TARGET"; rm -rf $ VARIANT
toegevoegd de auteur peterphonic, de bron
@ peterphonic: in dit geval zou een db zoals sqlite beter geschikt kunnen zijn om de werkstatus bij te houden.
toegevoegd de auteur jfs, de bron