zsh-users
 help / color / mirror / code / Atom feed
* Correct way to set environment
@ 2012-12-15 13:29 Florian Lindner
  2012-12-15 13:44 ` Stefan Marx
                   ` (3 more replies)
  0 siblings, 4 replies; 6+ messages in thread
From: Florian Lindner @ 2012-12-15 13:29 UTC (permalink / raw)
  To: zsh-users

Hello,

I'm a bit puzzled about the way to set global environment variables.

I've ushed .zshenv for that purpose since it is sourced on every shell
invocation.

florian@horus ~ % cat .zshenv
PATH=$HOME/flof/src:$HOME/software/bin:$PATH
PATH=/home/florian/software/src/boar:$PATH

PYTHONPATH=$HOME/flof/src:$PYTHONPATH


No other relevant z-files are present. This works as far as it sets
the PYTHONPATH variable but if I launch python it is not taken into
account. When I use export PYTHONPATH, the pythonpath gets longer and
longer if I invoke a zsh session within a zsh session.

What is the best way to set some environment variables, no matter how
(login, interactive, ...) the shell is invoced?

Thanks,

Florian


^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: Correct way to set environment
  2012-12-15 13:29 Correct way to set environment Florian Lindner
@ 2012-12-15 13:44 ` Stefan Marx
  2012-12-15 18:33 ` Peter Stephenson
                   ` (2 subsequent siblings)
  3 siblings, 0 replies; 6+ messages in thread
From: Stefan Marx @ 2012-12-15 13:44 UTC (permalink / raw)
  To: Florian Lindner; +Cc: zsh-users

Hi Florian,

Have you tried to export the vars? Then subprocesses should see the values.

Greetings from Cologne, Germany,
cu Stefan

--
Stefan Marx <Stefan.Marx@marx-consulting.com>
+49 171-2116079

Am 15.12.2012 um 14:29 schrieb Florian Lindner <mailinglists@xgm.de>:

> Hello,
> 
> I'm a bit puzzled about the way to set global environment variables.
> 
> I've ushed .zshenv for that purpose since it is sourced on every shell
> invocation.
> 
> florian@horus ~ % cat .zshenv
> PATH=$HOME/flof/src:$HOME/software/bin:$PATH
> PATH=/home/florian/software/src/boar:$PATH
> 
> PYTHONPATH=$HOME/flof/src:$PYTHONPATH
> 
> 
> No other relevant z-files are present. This works as far as it sets
> the PYTHONPATH variable but if I launch python it is not taken into
> account. When I use export PYTHONPATH, the pythonpath gets longer and
> longer if I invoke a zsh session within a zsh session.
> 
> What is the best way to set some environment variables, no matter how
> (login, interactive, ...) the shell is invoced?
> 
> Thanks,
> 
> Florian


^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: Correct way to set environment
  2012-12-15 13:29 Correct way to set environment Florian Lindner
  2012-12-15 13:44 ` Stefan Marx
@ 2012-12-15 18:33 ` Peter Stephenson
  2012-12-15 18:42 ` Philippe Troin
  2012-12-15 19:19 ` Bart Schaefer
  3 siblings, 0 replies; 6+ messages in thread
From: Peter Stephenson @ 2012-12-15 18:33 UTC (permalink / raw)
  To: zsh-users

On Sat, 15 Dec 2012 14:29:24 +0100
Florian Lindner <mailinglists@xgm.de> wrote:
> I'm a bit puzzled about the way to set global environment variables.
> 
> I've ushed .zshenv for that purpose since it is sourced on every shell
> invocation.
> 
> florian@horus ~ % cat .zshenv
> PATH=$HOME/flof/src:$HOME/software/bin:$PATH
> PATH=/home/florian/software/src/boar:$PATH
> 
> PYTHONPATH=$HOME/flof/src:$PYTHONPATH
> 
> 
> No other relevant z-files are present. This works as far as it sets
> the PYTHONPATH variable but if I launch python it is not taken into
> account. When I use export PYTHONPATH, the pythonpath gets longer and
> longer if I invoke a zsh session within a zsh session.
> 
> What is the best way to set some environment variables, no matter how
> (login, interactive, ...) the shell is invoced?

There are various things here:

(i) you need to ensure variables get exported, as Stefan pointed out, so
use the "export" keyword.  You don't need to do this every time you set the
variable, only once within each shell;

(ii) you need to put them in a file that gets sourced for all shells
(except when you give the "-f" option when starting the shell): .zshenv
is fine, as long as you understand the effect, though for some reason
this occasionally inspires holy wars (I think on the basis that
sometimes people don't understand the effect);

(iii) you don't want the paths to keep getting extended with repeated
values: for this, zsh has the -U (unique) keyword.  It only works on
colon-separated arrays if the shell knows that's what they are.  To do
that, you can associate the array with ("tie" it to) a real array ---
you can still set the colon-separated array, however, so if you want you
can ignore the real array completely.  This is already done for you for
PATH and path, because they're special, but you need to do it explicitly
for PYTHONPATH and pythonpath.  (PATH is probably already exported but
it doesn't have the -U flag by default; I've used the "export" keyword
anyway to express the intention.)

So put the following in .zshenv:


export -U PATH=$HOME/flof/src:$HOME/software/bin:$PATH
PATH=/home/florian/software/src/boar:$PATH
 
export -TU PYTHONPATH=$HOME/flof/src:$PYTHONPATH pythonpath


-- 
Peter Stephenson <p.w.stephenson@ntlworld.com>
Web page now at http://homepage.ntlworld.com/p.w.stephenson/


^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: Correct way to set environment
  2012-12-15 13:29 Correct way to set environment Florian Lindner
  2012-12-15 13:44 ` Stefan Marx
  2012-12-15 18:33 ` Peter Stephenson
@ 2012-12-15 18:42 ` Philippe Troin
  2012-12-15 19:19 ` Bart Schaefer
  3 siblings, 0 replies; 6+ messages in thread
From: Philippe Troin @ 2012-12-15 18:42 UTC (permalink / raw)
  To: Florian Lindner; +Cc: zsh-users

On Sat, 2012-12-15 at 14:29 +0100, Florian Lindner wrote:
> I'm a bit puzzled about the way to set global environment variables.
> 
> I've ushed .zshenv for that purpose since it is sourced on every shell
> invocation.
> 
> florian@horus ~ % cat .zshenv
> PATH=$HOME/flof/src:$HOME/software/bin:$PATH
> PATH=/home/florian/software/src/boar:$PATH
> 
> PYTHONPATH=$HOME/flof/src:$PYTHONPATH
> 
> 
> No other relevant z-files are present. This works as far as it sets
> the PYTHONPATH variable but if I launch python it is not taken into
> account. When I use export PYTHONPATH, the pythonpath gets longer and
> longer if I invoke a zsh session within a zsh session.

First thing:  unless the variable is exported, it remains as a shell
variable and does not get into the environment.  You do need to export
the variable.

When you do this, as you have noticed, because .zshenv is sourced at
every subshell invocation, the path keeps growing because you keep
appending or prepending values to the path every time.

> What is the best way to set some environment variables, no matter how
> (login, interactive, ...) the shell is invoced?

You could use a guard environment variable:

        if [[ $MY_ENVIRONMENT != yes ]]
        then
          export PATH=$HOME/flof/src:$HOME/software/bin:$PATH
          export PATH=/home/florian/software/src/boar:$PATH
          export PYTHONPATH=$HOME/flof/src:$PYTHONPATH
          export MY_ENVIRONMENT=yes
        fi

Or you could only append a path to these variables if they don't contain
it already.

Phil.


^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: Correct way to set environment
  2012-12-15 13:29 Correct way to set environment Florian Lindner
                   ` (2 preceding siblings ...)
  2012-12-15 18:42 ` Philippe Troin
@ 2012-12-15 19:19 ` Bart Schaefer
  2012-12-15 19:34   ` Bart Schaefer
  3 siblings, 1 reply; 6+ messages in thread
From: Bart Schaefer @ 2012-12-15 19:19 UTC (permalink / raw)
  To: zsh-users

On Dec 15,  2:29pm, Florian Lindner wrote:
}
} I've ushed .zshenv for that purpose since it is sourced on every shell
} invocation.

So far so good.

} No other relevant z-files are present. This works as far as it sets
} the PYTHONPATH variable but if I launch python it is not taken into
} account. When I use export PYTHONPATH, the pythonpath gets longer and
} longer if I invoke a zsh session within a zsh session.

You do need to export any variable that you want passed down to child
processes of the shell, such as the python interpreter.  PATH is one
of the variables exported by default, but PYTHONPATH is not.

I think you'll note that PATH is similarly getting longer every time.

The solution to this is to test whether the value already contains the
substring you're going to add, and skip the assignment if it would be
redundant.  You can do this yourself --

    export PYTHONPATH
    if [[ $PYTHONPATH != $HOME/flof/src:* ]];
    then PYTHONPATH=$HOME/flof/src:$PYTHONPATH
    fi

-- or you can let zsh do it by declaring the variable to be an array
containing unique values.

At startup, zsh "ties" the array variable $path to the environment string
$PATH.   If you run

    print $path
    print $PATH

you should see strings that are identical except that the first one has
spaces where the second has colons.  (If instead you see only the first
element of $PATH when printing $path, you have the ksharrays option set,
and must use ${path[@]} instead.)

With this connection, anything assigned to path is copied to PATH and
vice-versa, so now you can do:

    path=(~/flof/src $path)

You can set up a similar equivalence yourself with the typeset command:

    typeset -T PYTHONPATH pythonpath
    pythonpath=(~/flof/src $pythonpath)

With this is place, you can declare the array values to be unique:

    typeset -U path pythonpath

Zsh then collapses duplicates out of the arrays and updates the "tied"
strings to match.  Note, however, that if you assign directly to the
string variable instead of assigning to the array, then zsh does NOT
apply the uniqueness property, so you must remember to use the array
assignment form after tying.

There is one exception to the above:  If you combine creating the "tie"
along with the assignment into a single command, the uniqueness property
applies.

    typeset -UTx PYTHONPATH=$HOME/flof/src:$PYTHONPATH pythonpath

You can also use

    export -UT PYTHONPATH=$HOME/flof/src:$PYTHONPATH pythonpath

if you think that reads better.

This doesn't work for $path because it's already "special", so you must
fix that one up in two steps.

    path=(~/flof/src $path)
    typeset -U path

Enjoy.


^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: Correct way to set environment
  2012-12-15 19:19 ` Bart Schaefer
@ 2012-12-15 19:34   ` Bart Schaefer
  0 siblings, 0 replies; 6+ messages in thread
From: Bart Schaefer @ 2012-12-15 19:34 UTC (permalink / raw)
  To: zsh-users

On Dec 15,  6:33pm, Peter Stephenson wrote:
}
} (iii) you don't want the paths to keep getting extended with repeated
} values: for this, zsh has the -U (unique) keyword.  It only works on
} colon-separated arrays if the shell knows that's what they are.

On Dec 15, 11:19am, Bart Schaefer wrote:
}
} Zsh then collapses duplicates out of the arrays and updates the "tied"
} strings to match.  Note, however, that if you assign directly to the
} string variable instead of assigning to the array, then zsh does NOT
} apply the uniqueness property, so you must remember to use the array
} assignment form after tying.

Apparently I get to learn (or re-learn) something today as well.

I've never to my recollection attempted to apply -U to the string part
of a tied pair.  So my statement above applies only when the array part
has been declared unique but the string part has not.

(Most likely this is because my .zsh* files are written to work with any
version clear back to 2.4 from the mid-90s, and -U was not originally a
property of scalar variables.)


^ permalink raw reply	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2012-12-15 19:34 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2012-12-15 13:29 Correct way to set environment Florian Lindner
2012-12-15 13:44 ` Stefan Marx
2012-12-15 18:33 ` Peter Stephenson
2012-12-15 18:42 ` Philippe Troin
2012-12-15 19:19 ` Bart Schaefer
2012-12-15 19:34   ` Bart Schaefer

Code repositories for project(s) associated with this public inbox

	https://git.vuxu.org/mirror/zsh/

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).