New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Ability to specify environment variables to be used with the run function #259
Comments
There's no explicit support for this yet, but since Invoke is primary concerned with local-to-system shell commands, you should be able to modify So this sort of thing ought to Just Work (tm): import os
from invoke import run
my_vars = {'FOO': 'bar'}
os.environ.update(my_vars)
run("echo $FOO") # => should result in stdout of "bar" That's not to say we won't add a 'helper' for this (i.e. a contextmanager that modifies |
Thanks so much for your reply @bitprophet, this will do for now. I'm all in favour of allowing us to pass in the env kwarg. The only con with the approach above (that modifies os.environ) is that it modifies os.environ for the entire script, one would need to save the original and restore it afterwards if they wanted to be a little neater 😄 A simple context manager would probably also do the trick, something like this (not tested yet): def environ(env):
original_environ = os.environ.copy()
os.environ.update(env)
yield
os.environ = original_environ Anyways, thanks a lot for all your help and have a lovely weekend! Cheers |
OK, so I thought I had a nice neat little solution here: from contextlib import contextmanager
import os
@contextmanager
def environ(env):
original_environ = os.environ.copy()
os.environ.update(env)
yield
os.environ = original_environ
print os.environ.get('name')
with environ({'name': 'Invoke Me :o'}):
print os.environ.get('name')
print os.environ.get('name') Output:
But ti seems that invoke is doing something which doesn't like this solution 😢 from invoke import task, run
@task
def runme():
run('echo 1: $name')
with environ({'name': 'Invoke Me :o'}):
run('echo 2: $name')
run('echo 3: $name') Output:
Cheers |
Invoke isn't doing anything to When I test, it looks like my initial assertion is actually false: >>> os.environ['WHAT'] = 'THE HECK?'
>>> os.environ.get('WHAT')
'THE HECK?'
>>> run("env | grep LANG")
LANG=en_US.UTF-8
<invoke.runners.Result object at 0x1044510d0>
>>> run("env | grep WHAT")
<kaboom because grep exited 1 due to no matches> So that's egg on my face :) turns out we do need a specific feature for this after all! |
Hrm, I'm confused by the stdlib right now, here's the skinny:
|
Running some quick tests, neither |
Firstly, thanks for all your efforts on this, really appreciate it! 😄 Interestingly, things work differently on my Red Hat box here: Python 2.6.6 (r266:84292, Nov 21 2013, 10:50:32)
[GCC 4.4.7 20120313 (Red Hat 4.4.7-4)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import os
>>> from invoke import run
>>> os.environ['WHAT'] = 'THE HECK?'
>>> os.environ.get('WHAT')
'THE HECK?'
>>> run("env | grep LANG")
LANG=en_US.UTF-8
<invoke.runners.Result object at 0x1a10310>
>>> run("env | grep WHAT")
WHAT=THE HECK?
<invoke.runners.Result object at 0x1a19f10>
>>> In my testing, both subprocess and os.execve seemed to honour the environment variables set in os.environ. Edit: Hmm, tested on OS X with Python 2.7 and 2.6 and both got the environment variable. Cheers |
Which OS X, and are those the system Python interpreters or e.g. installed via brew? I was on Yosemite (10.10.4) and using its system python 2.6(.9). Also I think I never checked which Invoke version you're running on, though this still doesn't feel like anything our own code would be affecting, given my subprocess+execv test. |
@bitprophet sorry for the late reply on this, this is OS X 10.10 with Homebrew versions of Python, but also tested with the Python that ships and it's fine too 😄 |
There is another concern here. Changing |
@frol Very good point. This is a good argument for passing env directly to subprocess instead of manipulating |
See the last bullet point here - #259 (comment) - I noted that it's an option and yea, right now I can't see a great argument for anything but the "clean env" (obviously, with option for basing that dict on the current value of |
Thanks @bitprophet 😄 |
Poking this now (personal itch-scratch...:D). The timeline is hazy now but I'm not sure why I was implying we were no longer using
So I'll move forward with using both of those approaches as necessary and see how well it works. (Meaning, yes - as before, only using |
|
The 'behavior' kwarg (which would default to '
My inclination, which isn't strong, is that |
Hm, well, or we could do this - two dict kwargs:
But then we'd need to handle the case when both are given, probably by exploding as per the Zen of Python Will think about this for a bit. (Isn't this stream of consciousness so exciting?) |
Eh, I think an updating |
All done. At least, works well enough for me to use it in a crummy personal script that needed to run shell commands with a tweaked env. |
Huge thanks @bitprophet!! Really appreciate the efforts on this. I'll be sure to try it out soon and report back 😄 |
@bitprophet not sure I'm doing it well but running this
I was expecting I'm quite new to pyinvoke so maybe I'm wrong with achieving this. |
It isn't working for me either. |
@francbartoli and anyone curious about this:
This is not the behavior you should expect. Compare to the equivalent shell script, which also displays the behavior you have observed: GEOSERVER_LOCATION=bar env
env Environment variables are just set for running one command at a time. If you want to make an envvar available to multiple commands, you need to do something like this
Read here:
|
Thx @micahjsmith, it is clearer now |
This is a neat solution, however it fails on repeated invocation as does not restore the original
|
Hey there, love invoke.
In fabric, we have
with shell_env(...)
so that a particular set of environment variables will be used in a particular scope, which apply to commands being run.Is there any way to currently accomplish this with invoke?
I would really love to switch back to it, but I've reluctantly switched to paver until I can figure this out.
Thanks
Fotis
The text was updated successfully, but these errors were encountered: