0

I've been refactoring a bash script that uses the special RANDOM linux environment variable. This variable provides random integers when accessed.

From another SO question:

RANDOM Each time this parameter is referenced, a random integer between 0 and 32767 is generated. The sequence of random numbers may be initialized by assigning a value to RANDOM. If RANDOM is unset, it loses its special properties, even if it is subsequently reset.

Here's an example of the expected output, working correctly:

ubuntu:~$ echo ${RANDOM}
19227
ubuntu:~$ echo ${RANDOM}
31030

However, when I try to replicate its usage in python I was surprised to find that it does not seem to work.

>>> import os
>>> os.environ.get('RANDOM')
(No output)
>>> os.environ.get('RANDOM')==None
True

This is quite unexpected. Obviously I can just replicate the random integer behavior I want using

random.randint(0, 32767)

But other scripts may be relying on the environment variables specific value (You can seed RANDOM by writing to it), so why can I not simply read this variable in python as expected?

code11
  • 1,986
  • 5
  • 29
  • 37
  • 4
    It's not an environment variable, it's a a shell built-in variable. If it were an environment variable, how could it change each time you use it? – Barmar Aug 29 '22 at 15:48
  • There are plenty of older examples of special registers with strange behavior implemented through underlying hardware. If I can access PATH and other shell variables with os.environ, why not this one? – code11 Aug 29 '22 at 16:12
  • There's nothing special about PATH. – Barmar Aug 29 '22 at 16:18
  • 1
    Shell variables become environment variables when you use `export` in the shell. I'm not sure what would happen if you export `RANDOM`, though. – Barmar Aug 29 '22 at 16:18
  • If PATH and HOME are built in shell variables, and I can access them without any additional export via os.environ.get, it is expected that I should also be able to access RANDOM in this fashion as well. – code11 Aug 29 '22 at 16:20
  • 1
    They're environment variables that the shell inherits, not shell variables. – Barmar Aug 29 '22 at 16:20
  • Ok, thats clear. Another example with the same behavior seems to be SECONDS. Honestly your last two comments are elucidating enough to together be a good answer to this question. If you add it, I would accept. – code11 Aug 29 '22 at 16:21

2 Answers2

1

RANDOM is a shell variable, not an environment variable. You need to export it to get it into the environment:

imac:barmar $ export RANDOM
imac:barmar $ python
Python 3.9.2 (v3.9.2:1a79785e3e, Feb 19 2021, 09:06:10) 
[Clang 6.0 (clang-600.0.57)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import os
>>> os.environ['RANDOM']
'15299'

However, this just puts the most recent value of RANDOM in the environment, it won't change each time you use os.environ['RANDOM'] the way $RANDOM does when you use it in the shell.

Barmar
  • 741,623
  • 53
  • 500
  • 612
  • I'll give it a couple of hours for anyone else to comment in as well, but this seems good. I wish there were a section in documentation of os.environ.get that warned about this since the distinction between environment variables and built-in shell variables may not be clear to the uninitiated. – code11 Aug 29 '22 at 16:27
  • And for anyone looking for more reference, [here](https://www.gnu.org/software/bash/manual/html_node/Bash-Variables.html) is a list of built-in bash variables (Note RANDOM, SECONDS, and PATH) – code11 Aug 29 '22 at 19:17
  • This doesn't work in general because, as I'm sure you know @barmar, `RANDOM` is a magic variable whose value changes each time it is used. That isn't true if you export it since the value of the `RANDOM` env var is then static. It seems to me you completely missed the point of the O.P.'s question. – Kurtis Rader Aug 30 '22 at 03:43
0

RANDOM is a POSIX shell magic variable whose value changes each time you use $RANDOM. If you export it, as suggested by @Barmar's answer, the value is static. That is, it does not change each time you use that env var. Environment variables are, by definition, simple key=value strings. Which means the value doesn't magically change each time you reference key (e.g., when doing os.environ['RANDOM']). If you want a random integer in Python you should use something like random.randint(0, 32767) as you noted in your question.

I get the sense you have a fundamental misunderstanding of what environment variables are and how they behave.

Kurtis Rader
  • 6,734
  • 13
  • 20