代码之家  ›  专栏  ›  技术社区  ›  physicsmichael

为什么不能在python中设置环境变量?

  •  37
  • physicsmichael  · 技术社区  · 16 年前

    我希望编写一个python脚本,通过在我将要执行一些模拟代码的任何目录中运行该脚本来创建一些适当的环境变量,并且我已经阅读到,我不能编写一个脚本来使这些env var在mac os终端中保持不变。所以有两件事:

    这是真的吗?

    这似乎是一件有用的事情;为什么一般来说不可能呢?

    6 回复  |  直到 16 年前
        1
  •  31
  •   Benson    16 年前

    你不能从Python中完成,但是一些聪明的bash技巧可以完成类似的工作。基本的推理是:环境变量存在于每个进程的内存空间中。使用fork()创建新进程时,它继承其父进程的环境变量。当您在shell(例如bash)中设置环境变量时,如下所示:

    export VAR="foo"
    

    您要做的是告诉bash将其进程空间中的变量var设置为“foo”。运行程序时,bash使用fork()然后exec()来运行程序,因此从bash运行的任何内容都继承bash环境变量。

    现在,假设您想要创建一个bash命令,该命令使用当前目录中名为“.data”的文件中的内容设置一些环境变量数据。首先,您需要有一个命令来从文件中获取数据:

    cat .data
    

    打印数据。现在,我们要创建一个bash命令来在环境变量中设置该数据:

    export DATA=`cat .data`
    

    该命令获取.data的内容并将其放入环境变量数据中。现在,如果您将它放在alias命令中,那么您就有了一个bash命令,用于设置环境变量:

    alias set-data="export DATA=`cat .data`"
    

    您可以将该别名命令放入主目录中的.bashrc或.bash_概要文件中,以便在启动的任何新bash shell中都可以使用该命令。

        2
  •  17
  •   dbr    12 年前

    一个解决方法是输出 export 命令,并让父shell对此进行计算。

    thescript.py :

    import pipes
    import random
    r = random.randint(1,100)
    print("export BLAHBLAH=%s" % (pipes.quote(str(r))))
    

    …和bash别名(在大多数shell中也可以这样做..甚至TCSH!:

    alias setblahblahenv="eval $(python thescript.py)"
    

    用途:

    $ echo $BLAHBLAH
    
    $ setblahblahenv
    $ echo $BLAHBLAH
    72
    

    您可以输出任意shell代码,包括多个命令,如:

    export BLAHBLAH=23 SECONDENVVAR='something else' && echo 'everything worked'
    

    记住要小心转义任何动态创建的输出 pipes.quote 模块适用于此)

        3
  •  3
  •   Stefano Borini    16 年前

    如果在Python脚本(或任何其他脚本或程序)中设置环境变量,它不会影响父shell。

    编辑澄清: 所以你的问题的答案是,是真的。 但是,您可以从shell脚本中导出,并使用点调用对其进行源代码调用。

    在FooExpP.SH中

    export FOO="bar"
    

    在命令提示下

    $ . ./fooexport.sh
    $ echo $FOO
    bar
    
        4
  •  2
  •   Joe Holloway    16 年前

    我喜欢在shell脚本中使用/usr/bin/env在我发现自己处于类似情况时“包装”命令行:

    #!/bin/bash
    
    /usr/bin/env NAME1="VALUE1" NAME2="VALUE2" ${*}
    

    所以让我们称这个脚本为“myappenv”。我把它放在$home/bin目录中,这是我的$path目录。

    现在,我可以使用该环境调用任何命令,只需在“myappenv”前面加上以下内容:

    myappenv dosometask -xyz
    

    其他张贴的解决方案也可以,但这是我个人的偏好。一个优点是环境是暂时的,所以如果我在shell中工作,那么只有我调用的命令会受到更改后的环境的影响。

    基于新评论的修改版本

    #!/bin/bash
    
    /usr/bin/env G4WORKDIR=$PWD ${*}
    

    你也可以用别名把这些都包装起来。我更喜欢包装脚本的方法,因为我倾向于在那里有其他的环境准备,这使我更容易维护。

        5
  •  1
  •   Joe Koberg    16 年前

    一般不可能。为python创建的新进程不能影响其父进程的环境。父级也不能影响子级,但父级可以将子级的环境设置为新进程创建的一部分。

    也许你可以把它们放进去 .bashrc , .profile 或者在MacOS中使用等效的“登录时运行”或“在每个新终端会话上运行”脚本。

    您还可以让Python使用所需的环境启动模拟程序。(使用 env 子进程的参数.popen( http://docs.python.org/library/subprocess.html )

    import subprocess, os
    os.chdir('/home/you/desired/directory')
    subprocess.Popen(['desired_program_cmd', 'args', ...], env=dict(SOMEVAR='a_value') )
    

    或者让python把这样的shell脚本写到一个文件中, .sh 扩展:

    export SOMEVAR=a_value
    cd /home/you/desired/directory
    ./desired_program_cmd
    

    然后 chmod +x 它可以在任何地方运行。

        6
  •  0
  •   Niall    9 年前

    正如Benson所回答的,但最好的方法是创建一个简单的bash函数来保存参数:

    upsert-env-var (){ eval $(python upsert_env_var.py $*); }
    

    在Python脚本中,您可以使用参数执行任何操作。要简单地添加变量,请使用如下内容:

    var = sys.argv[1]
    val = sys.argv[2]
    if os.environ.get(var, None):
        print "export %s=%s:%s" % (var, val, os.environ[var])
    else:
        print "export %s=%s" % (var, val)
    

    用途:

    upsert-env-var VAR VAL