Как использовать экспорт с Python на Linux - PullRequest
51 голосов
/ 01 октября 2009

Мне нужно сделать такой экспорт в Python:

# export MY_DATA="my_export"

Я пытался сделать:

# -*- python-mode -*-
# -*- coding: utf-8 -*-
import os
os.system('export MY_DATA="my_export"')

Но когда я перечисляю экспорт, «MY_DATA» не появляется:

# export

Как я могу сделать экспорт с Python без сохранения «my_export» в файл?

Ответы [ 11 ]

75 голосов
/ 02 октября 2009

export - это команда, которую вы даете непосредственно оболочке (например, bash), чтобы она добавила или изменила одну из переменных среды. Вы не можете изменить среду вашей оболочки от дочернего процесса (такого как Python), это просто невозможно.

Вот что с тобой происходит, попробуй os.system('export MY_DATA="my_export"') ...

/bin/bash process, command `python yourscript.py` forks python subprocess
 |_
   /usr/bin/python process, command `os.system()` forks /bin/sh subprocess
    |_
      /bin/sh process, command `export ...` changes local environment

Когда самый нижний подпроцесс /bin/sh заканчивает выполнение вашей команды export ..., он сбрасывается вместе со средой, которую вы только что изменили.

64 голосов
/ 01 октября 2009

Вы действительно хотите сделать

import os
os.environ["MY_DATA"] = "my_export"
12 голосов
/ 28 января 2014

Другой способ сделать это, если вы спешите и не возражаете против случайного послевкусия, это выполнить вывод скрипта python в вашей среде bash и распечатать команды для выполнения установки среды в питон. Не идеально, но это может сделать работу в крайнем случае. Это не очень переносимо между оболочками, так что YMMV.

$(python -c 'print "export MY_DATA=my_export"')

(вы также можете заключить оператор в кавычки в некоторых оболочках ``)

8 голосов
/ 01 октября 2009

Не все так просто:

python -c "import os; os.putenv('MY_DATA','1233')"
$ echo $MY_DATA # <- empty

Но:

python -c "import os; os.putenv('MY_DATA','123'); os.system('bash')"
$ echo $MY_DATA #<- 123
1 голос
/ 01 октября 2009

Вместо этого вы можете попробовать os.environ ["MY_DATA"].

0 голосов
/ 24 июня 2019
import os
import shlex
from subprocess import Popen, PIPE


os.environ.update(key=value)

res = Popen(shlex.split("cmd xxx -xxx"), stdin=PIPE, stdout=PIPE, stderr=PIPE,
            env=os.environ, shell=True).communicate('y\ny\ny\n'.encode('utf8'))
stdout = res[0]
stderr = res[1]

0 голосов
/ 18 апреля 2019

У меня отличный ответ.

#! /bin/bash

output=$(git diff origin/master..origin/develop | \
python -c '
  # DO YOUR HACKING
  variable1_to_be_exported="Yo Yo"
  variable2_to_be_exported="Honey Singh"
  … so on
  magic=""
  magic+="export onShell-var1=\""+str(variable1_to_be_exported)+"\"\n"
  magic+="export onShell-var2=\""+str(variable2_to_be_exported)+"\""  
  print magic
'
)

eval "$output"
echo "$onShell-var1" // Output will be Yo Yo
echo "$onShell-var2" // Output will be Honey Singh

Мистер Алекс Тингл прав насчет этих процессов и субпроцессов

Как это может быть достигнуто, как я уже упоминал выше. Ключевая концепция:

  1. Все, что printed из python будет сохранено в переменной в переменной перехвата в bash [output]
  2. Мы можем выполнить любую команду в виде строки, используя eval
  3. Итак, подготовьте ваш вывод print из python в значимых bash командах
  4. используйте eval для выполнения в bash

И вы можете увидеть ваши результаты

Примечание Всегда выполняйте eval, используя double quotes, иначе bash испортит ваши \n с, и результаты будут странными

PS: я не люблю bash, но вы должны его использовать

0 голосов
/ 22 февраля 2018

Однолинейное решение:

eval `python -c 'import sysconfig;print("python_include_path={0}".format(sysconfig.get_path("include")))'`
echo $python_include_path  # prints /home/<usr>/anaconda3/include/python3.6m" in my case

Разбивка:

вызов Python

python -c 'import sysconfig;print("python_include_path={0}".format(sysconfig.get_path("include")))'

Он запускает скрипт на Python, который

  1. import sysconfig
  2. получает путь включения питона, соответствующий этому двоичному файлу питона (используйте «какой питон», чтобы увидеть, какой из них используется)
  3. печатает скрипт "python_include_path = {0}", где {0} является путем от 2

Eval call

eval `python -c 'import sysconfig;print("python_include_path={0}".format(sysconfig.get_path("include")))'`

В текущем экземпляре bash он выполняет вывод из скрипта python. В моем случае его выполнение:

python_include_path=/home/<usr>/anaconda3/include/python3.6m

Другими словами, он устанавливает переменную среды "python_include_path" с этим путем для этого экземпляра оболочки.

По мотивам: http://blog.tintoy.io/2017/06/exporting-environment-variables-from-python-to-bash/

0 голосов
/ 18 декабря 2017

В надежде дать ясность по поводу общей синфузии ...

Я написал много python <-> bash <-> elfbin toolchains, и правильный способ увидеть это так:

Каждый процесс (отправитель) имеет состояние среды, унаследованное от того, что его вызвало. Любые изменения остаются локальными для этого процесса. Передача состояния среды сама по себе является функцией и выполняется в двух направлениях, каждое со своими оговорками. Самым распространенным является изменение среды перед запуском подпроцесса. Чтобы перейти к металлу, посмотрите на вызов exec () в C. Есть вариант, который принимает указатель на данные среды. Это единственная реально поддерживаемая передача среды в типичных ОС.

Сценарии оболочки создадут состояние, которое будет передаваться при запуске дочерних элементов при выполнении экспорта . В противном случае он просто использует то, что получил в первую очередь.

Во всех остальных случаях это будет некоторый общий механизм, используемый для передачи набора данных, чтобы позволить самому вызывающему процессу обновить свое окружение на основе результата вывода дочерних процессов.

Ex:

ENVUPDATE = $(CMD_THAT_OUTPUTS_KEYVAL_LISTS)
echo $ENVUPDATE > $TMPFILE
source $TMPFILE

Конечно, то же самое можно сделать с помощью json, xml или других вещей, если у вас есть инструменты для интерпретации и применения.

Необходимость в этом может быть (с вероятностью 50%) признаком неверного истолкования базовых примитивов и того, что вам нужно улучшить конфигурацию или обмен параметрами в вашем решении .....

О, в Python я бы сделал что-то вроде ... (требуется улучшение в зависимости от вашей ситуации)

import re

RE_KV=re.compile('([a-z][\w]*)\s*=\s*(.*)')

OUTPUT=RunSomething(...) (Assuming 'k1=v1 k2=v2')

for kv in OUTPUT.split(' ')
  try:
    k,v=RE_KV.match(kv).groups()
    os.environ[k]=str(v)
  except:
    #The not a property case...
    pass
0 голосов
/ 12 декабря 2017

Это своего рода хак, потому что на самом деле Python здесь не делает ничего особенного, но если вы запустите команду экспорта в той же вложенной оболочке, вы, вероятно, получите нужный результат.

import os

cmd = "export MY_DATA='1234'; echo $MY_DATA" # or whatever command
os.system(cmd)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...