Python os.environ doesn't show empty environment variables - python

After an environment variable is exported and set to empty, I can't get its value in Python with os.environ. Is it expected?
Examples:
## export TEST_ENV_VAR
(base) ➜ Code export | grep TEST_ENV_VAR
TEST_ENV_VAR=''
(base) ➜ Code python
Python 3.8.12 (default, Oct 12 2021, 13:49:34)
[GCC 7.5.0] :: Anaconda, Inc. on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import os
>>> 'TEST_ENV_VAR' in os.environ
False
## export TEST_ENV_VAR=''
(base) ➜ Code export | grep TEST_ENV_VAR
TEST_ENV_VAR=''
(base) ➜ Code python
Python 3.8.12 (default, Oct 12 2021, 13:49:34)
[GCC 7.5.0] :: Anaconda, Inc. on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import os
>>> 'TEST_ENV_VAR' in os.environ
True
## export TEST_ENV_VAR='TEST'
(base) ➜ Code export | grep TEST_ENV_VAR
TEST_ENV_VAR=TEST
(base) ➜ Code python
Python 3.8.12 (default, Oct 12 2021, 13:49:34)
[GCC 7.5.0] :: Anaconda, Inc. on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import os
>>> 'TEST_ENV_VAR' in os.environ
True
The three samples above run in three different new terminals. I modified the .zshrc file to export different values. What's the difference between export foo and export foo=''?

There is a difference between "Shell variables" and "Environment Variables" - see here - A shell variable is only available to the shell setting it whereas an environment variable is available to all child processes as well.
In bash - you can get the list of environment variables with env, and add to the environment variables with export
SHELL_VAR="10"
env | grep SHELL_VAR # No result
export ENV_VAR=100
env | grep ENV_VAR # ENV_VAR=100
Python shell (child process) picks the environment variables when you try an os.environ
'SHELL_VAR' in os.environ # False
'ENV_VAR' in os.environ # True

The issue is the way you are defining your variables.
When you just do:
export FOO
no variable is actually exported unless FOO has been defined previously:
FOO=''
export FOO
or concomitantly:
export FOO=''
If FOO appears in env | grep FOO, it should appear in os.environ.

Related

Using pwntools process interactive mode to control python3

I am trying to use pwntools to control a python3 session. Here is my code:
from pwn import process
r = process(['python3'])
r.interactive()
However, after I enter r.interactive(), when I type into the terminal, the python3 sub-process has strange reactions. At least I do not see my commands echoed back most of the times.
I also tried to call python3 in a bash session, but the same thing happens.
$ python3
Python 3.8.5 (default, Jan 27 2021, 15:41:15)
[GCC 9.3.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> from pwn import process
>>> r = process(['bash'])
[x] Starting local process '/usr/bin/bash'
[+] Starting local process '/usr/bin/bash': pid 119080
>>> r.interactive()
[*] Switching to interactive mode
echo hello
hello
echo this is bash
this is bash
python3
print(1)
print(2)
print(3)
exit
echo hello
File "<stdin>", line 5
echo hello
^
SyntaxError: invalid syntax
Why is this happening? Is it a bug in pwntools, or are there some configurations I overlook?
You need to specify the PTY in your shell, so like this:
$ python3
Python 3.9.2 (default, Feb 28 2021, 17:03:44)
[GCC 10.2.1 20210110] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> from pwn import *; r = process(['python3'], stdin=PTY, raw=False); r.interactive()
[x] Starting local process '/usr/bin/python3'
[+] Starting local process '/usr/bin/python3': pid 2984281
[*] Switching to interactive mode
Python 3.9.2 (default, Feb 28 2021, 17:03:44)
[GCC 10.2.1 20210110] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> 1+1
1+1
2
>>>

eshell starts python IDLE instead of running script when editing remotely

With Emacs 24.3.1, I get this when editing through Tramp/ssh in eshell:
/<remotepath> $ bash
/<remotepath> $ python test.py
hello world!
/<remotepath> $ exit
exit
/<remotepath> $ python test.py
Python 2.6.6 (r266:84292, Oct 12 2012, 14:23:48)
[GCC 4.4.6 20120305 (Red Hat 4.4.6-4)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>>
The file test.py is:
print "hello world!"
Bash is version 4.1.2. Does anyone have any explanation for this behavior?
I don't know eshell, but my guess is you forget to pass the positional parameters when creating your alias:
# don't forget the quotes
# ▼ ▼
~ $ alias python '/path/to/alternate/python $*'
# ▲▲
# don't forget positional parameters
See http://www.emacswiki.org/emacs/EshellAlias

How to set system variable on mac? Since i could not get the system variable by using python 3 os.getenv or os.environ

I am pretty sure i've set the system variable as following:
echo 'export TEST=/path/test' >> .bash_profile
echo 'export TEST=/path/test' >> .zshrc
And it is possible to get the variable from terminal just like:
echo $TEST
#the '/path/test' was print out
But i could not get it from python 3, as following:
TEST = os.getenv('TEST')
or
TEST = os.environ['TEST']
Does anyone know why? Any clue would be appreciated
You seem to be confused by the distinction between environment variables and (as you put it) system variables. When you run
echo 'export TEST=/path/test' >> .bash_profile
echo 'export TEST=/path/test' >> .zshrc
What you are doing is setting environment variables. What happens is that when you start a shell subsystem, the OS calls certain startup files to set variables for your environment. If you are in a Bash shell, it will call .profile, .bash_profile, etc. When you get your shell, any variables you set in your startup scripts are set for your environment. So for instance:
pswaminathan ~ $ export TEST=/path/test
pswaminathan ~ $ python3
Python 3.4.0 (default, Mar 24 2014, 00:31:02)
[GCC 4.2.1 Compatible Apple LLVM 5.1 (clang-503.0.38)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import os
>>> os.getenv('TEST')
'/path/test'
But $TEST here is not set up at the system level. It is set up at the environment level. It relies on being set; in your case, by the .zshrc or .bash_profile file. If you are running a script by cron, for example, you can set your environment varaibles in the crontab. Or you can set your envvars in a shell script you're using to run these. So how are you running this file, where you're not getting the right environment variables?
Also good reference: http://en.wikipedia.org/wiki/Environment_variable

Disable python auto-escaping for environment variables

I am having the following problem with python, being used to generate
files on Linux, that are being read on Windows. Python is auto-escaping
the strings, so that when written to a file, they are incorrect.
In my shell I have the environment variable set to a UNC path:
camd011> setenv python_error "\\\\a\\b\\c"
camd011> echo $python_error
\\a\b\c
I then retrieve this in python, as it will be used to generate C code
and a #include directive. However when I retrieve the value in python:
camd011> python
Python 1.6.1 (#1, Oct 17 2013, 15:08:20) [GCC 4.4.7 20120313 (Red Hat 4.4.7-3)] on linux2
Copyright (c) 1995-2001 Corporation for National Research Initiatives.
All Rights Reserved.
Copyright (c) 1991-1995 Stichting Mathematisch Centrum, Amsterdam.
All Rights Reserved.
>>> import os
>>> value = os.environ['python_error']
>>> value
'\\\\\\\\a\\\\b\\\\c'
As you can see above it has been auto-escaped, thus when I write it to a file:
>>> f = open("temp.txt", "w")
>>> f.write(value)
>>> f.close()
I end up with double-slashes, instead of a proper UNC path, and the code
now fails to compile. File:
\\\\a\\b\\c
i.e. the code includes a #include which now fails:
#include "\\\\a\\b\\c\file.h"
How do I stop python from auto-escaping my environment variable?
This appears to be a problem with quoting and dequoting in tcsh. It has nothing to do with Python -- Python gets the same variable that you can print out with the env command.
It appears that in tcsh, echo $FOO de-quotes the value of $FOO before printing. This seems to have misled you about what is really in your environment variable, so you've added an extra layer of quoting.
unaha-closp:~> setenv FOO "\\hello\world"
unaha-closp:~> echo $FOO
\hello\world
unaha-closp:~> env | grep FOO
FOO=\\hello\world
unaha-closp:~> python
Python 2.7.3 (default, Sep 26 2013, 20:03:06)
[GCC 4.6.3] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import os
>>> print os.environ["FOO"]
\\hello\world
>>>
unaha-closp:~> bash
svk#unaha-closp:~$ echo $FOO
\\hello\world
The proper setenv command should simply be setenv python_error "\\a\b\c".

Is it possible to cross reference bash and python variables in python script

I can get a value n when I run a shell command using os.system in the python script, but I also need to sum it up to get a total number for subsequent computation in the python script,
total=0
for i in xrange(1,8):
os.system('n=$(qstat -n1 | grep -o node'+str(i)+' | wc -l) && echo $n')
Is it possible? Also is it possible to use python variable in shell command, something like
os.system('echo $total')
Use the shell's exportcommand:
$ export ABC=1 # Set and export var in shell
$ bash # Start another shell
$ echo $ABC # variable is still here
1
$ python # Start python still in the deeper shell
Python 2.7.2 (default, Oct 11 2012, 20:14:37)
[GCC 4.2.1 Compatible Apple Clang 4.0 (tags/Apple/clang-418.0.60)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> from os import environ # import environnement
>>> environ['ABC'] # And here's the variable again (it's a string because the shell doesn't have types)
'1'
You can subprocess module's check_output method like this
import subprocess
print sum(int(subprocess.check_output(["/bin/sh", "-c", "n=`expr {} + 1` && echo $n".format(i)])) for i in range(10))
Output
55

Categories

Resources