Reading user environment variables by os.environ - python-2.7

I have a setup script (not mine) which reads a certain system variable. I tried setting this in two ways:
Going to control panel > User Accounts > Change my environment variables
In command line: setx myvar myvalue
I set it as user variables, since i don't have the rights to set system variables. If i open a new command line window and type set, my variable shows there correctly.
However, if i start python and run the following script, i don't see my variable:
import os
print os.environ
I am using windows 10 and python 2.7. Modifying the code to get the variable is not possible since it is code from an external library.

Related

getenv() does not return last backslash

I am trying to read a env variable using getenv() in C++,
lets say env variable is
CONTENT_PATH=C:\Users\rat\Documents\fix\plat\gen\content\
It is being set by a batch file before program runs, contents of batch file.
set mypath=%~dp0
set gameContent=%mypath%plat\gen\content\
:: setting CONTENT_PATH
setx -m CONTENT_PATH "%gameContent%"
during debugging in visual studio, I am getting value as
C:\Users\rat\Documents\fix\plat\gen\content"
the last '\' is not coming, even though if I manually set the env variable value using Control Panel->Advance system settings.

Crontab No Longer Runs Raspberry Pi Python Script in Background But Still Runs Manually

I am able to run my Python script in the background to control two servos by automatically launching the script at boot up using sudo crontab -e. I modified the script so I am now continually writing the servos current position to a horz.txt and vert.txt file and using those files to initialize the steppers to their home position so I can find home position again after a power loss. The script works fine with the horz.txt and vert.txt code that I added when I manually launch the script from the command line on the black screen using sudo python mystepper6.py, but it doesn't launch automatically at startup nor does it show up as running when I type ps ax on the command line. I added a little extra code just to wiggle the servos before the main program starts and and the servos automatically wiggle as programmed in the sudo crontab -e but then it just stops and won't continue to find the home position. It seems to be something with the new code but I don't know what it could be. My sudo crontab -e line is #reboot (sleep2;python /home/pi/mystepper6.py) &. Below is the script for mystepper6.py.
The script below was shortened to show the relevant lines due to limited space available in this post. The sudo reboot hangs with no error message near the bottom where it is commented 'move to home position' (it doesn't move). I am able to print adjustv and adjusth integers prior to that point so the variables are properly assigned a value from the .txt files at that point. When I manually run mystepper6.py from the command line it runs perfectly.
I have spent waaay too many hours on this problem and have purchased two e-books to no avail. Please help.
import RPi.GPIO as gpio # import library RPi.GPIO gpio=use general purpose input output pin names
import time # import time library
PINSh = [27,10,18,23] # variable 'PINS' holds a list of gpio pin numbers
SEQAh = [(27,),(10,),(18,),(23,)]
PINSv = [4,17,22,24] # variable 'PINS' holds a list of gpio pin numbers
SEQAv = [(4,),(17,),(22,),(24,)]
DELAY = 0.01 # time between motor steps (too small of a number then the motor stalls)
alpha = 140 # horizontal full scale viewing angle in motor counts 128 counts = 360 degrees
beta = 30 # was 15 vertical full scale viewing angle in motor counts 128 counts = 360 degrees
gpio.setmode(gpio.BCM) # tells RPi.GPIO we want to use pin names (BCM is the mfg)
for pin in PINSh: # pin is a variable name assigned a new value each loop; PINS is a list
gpio.setup(pin, gpio.OUT) # this says we want to use 'pin' as an output
for pin in PINSv: # pin is a variable name assigned a new value each loop; PINS is a list
gpio.setup(pin, gpio.OUT)
def stepper(sequence, pins): # def says 'stepper' is the function name (like a variable), then parameters are inside ()
for step in sequence:
for pin in pins:
if pin in step:
gpio.output(pin, gpio.HIGH)
else:
gpio.output(pin, gpio.LOW)
webcam_horz_home = open("horz.txt", "a")
webcam_horz_home.close()
webcam_vert_home = open("vert.txt", "a")
webcam_vert_home.close()
# load last position prior to power down
webcam_horz_home = open("horz.txt", "r")
rows = webcam_horz_home.readlines();
for row in rows:
adjusth = int(row)
webcam_horz_home.close()
webcam_vert_home = open("vert.txt", "r")
rows = webcam_vert_home.readlines();
for row in rows:
adjustv = int(row)
webcam_vert_home.close()
counter = 0 # move to home position
while counter < adjustv:
stepper(SEQAv, PINSv)
counter = counter + 1
# CONTINUAL PAN AND TILT OPERATION (box pattern):
I just tested this on my Pi running Raspbian and it worked.
First, I created a python script called some_script.py in the primary user's home directory.
Script contents:
import sys
import time
with open("/home/username/some_script.py.out", "w") as f:
f.write(str(time.time()) + " " + "some_script.py RAN!\n")
Then, in the terminal, I set the executable bit on the file which allows it be executed:
sudo chmod +x some_script.py
Then, also in the terminal, I typed sudo crontab -e and added the following line at the bottom of the root user's crontab:
#reboot sleep 2; /usr/bin/python /home/username/some_script.py
I then rebooted, cded to /home/username/ and confirmed that python had run at reboot and written to a file:
cat some_script.py.out
1458062009.53 some_script.py RAN!
UPDATE / SOLUTION
After confirming that the OP was able to successfully replicate the steps above, I was fairly confident that this was not an issue stemming from varying implementations of cron on different *nix systems or some other edge case. As expected, he could run python via cron, he could use the #reboot feature and he could write to disk without any sort of permission issues.
However, it still didn't work. What did solve the issue was simply to use absolute paths rather than relative paths.
Changing
webcam_horz_home = open("horz.txt", "a")
to
webcam_horz_home = open("/home/pi/horz.txt", "a")
and
webcam_vert_home = open("vert.txt", "a")
to
webcam_vert_home = open("/home/pi/vert.txt", "a")
got OP's steppers purring again :)
EXPLANATION / BACKGROUND
When executing scripts or commands via the crontab of other users (in this case root), paths relative to the regular user's home directory (eg. ~/.bashrc) will no longer be valid or will point to a different file with the same filename if it exists. The same "issue" is sometimes seen when people run servers that call scripting languages such as PHP (often executed by the www-data user).
On a Raspberry Pi, these things can cause a bit of a catch-22 when working with GPIOs because the GPIO device is locked down and not accessible to unprivileged users without a change of permissions and groups.
If OP ran his script as root by adding the cron entry via sudo crontab -e, he would have access to the GPIO device (since root has access to almost everything). However, the relative paths in his python script that implicitly reference the home folder of the non-privileged user pi would no longer be valid (since home now means the folder /root which is the home folder of the root user).
If OP ran his scripts via the non-privileged pi user's crontab by adding the cron entries via crontab -e (without sudo), the paths would be valid (home or ~/ would now mean /home/pi/) but then he wouldn't have access to the GPIO device since pi is pretty unprivileged. Note: the #reboot feature is not available in all cron implementations (some embedded and stripped down *nix distros don't have it) and often it doesn't work for users other than root.
This means that OP had two options (there might be more; i'm no Linux guru):
place the files vert.txt and horz.txt in the home folder of the root user.
simply change the paths specified in the python script and keep running the script #reboot in root's crontab.
No. 2 is probably better since it keeps the home folder of root empty and keeps OP's files in pi's home folder. root should generally not be messed with unless there's no other options such as using sudo.

Passing the environment variables to the launched process bash script

Under linux, I have a bash script, that launches a c++ program binary.
What I need to do is set an environment variable in that script, and access that variable
inside the launched C++ program using getenv .
Here is the code for the script
#!/bin/bash
export SAMPLE_VAR=1
./c++_binary
The c++ program:
char * env_var = getenv("SAMPLE_VAR");
if (env_var != NULL) printf("var set\n");
However this does not seem to work. From what I understand is that when we execute the script, it will run in a new subshell and set the environment variable SAMPLE_BAR there, but the C++ binary is launched in the same subshell as well (may be I am wrong here) so it should have access to the SAMPLE_VAR. I even tried writing a separate script that just sets the env variable, and in the main script I called that script as source env_var_set.sh to no avail.
Is it possible to pass on a newly set environment variable to a program this way ?
Thanks
Since feature requests to mark a comment as an answer remain declined, I copy the above solution here.
Ah Sorry for the Typos, And my mistake, Inside the script I was launching the binary with 'sudo' which ran it in root's env and didnt have the variable set there. Removed sudo and it worked fine. Sorry for the confusion. Cheers. – Abdullah
First of all you need to source your shell script in order for the env variable to be set. and secondly include quotes in the getenv call.
char * env_var = getenv("SAMPLE_VAR");
if (env_var != NULL) printf("var set\n");

Python not calling an external program part 3

I have been having problems trying to run an external program from a python program that was generated from a trigger in a postgres 9.2 database. The trigger works. It writes to a file. I had tried just running the external program but the permissions would not allow it to run. I was able to create a folder (using os.system(“mkdir”) ). The owner of the folder is NETWORK SERVICE.
I need to run a program called sdktest. When I try to run it no response happens so I think that means that the python program does not have enough permissions (with an owner of NETWORK SERVICE) to run it.
I have been having my program copy files that it needs into that directory so they would have the correct permissions and that has worked to some degree but the program that I need to run is the last one and it is not running because it does not have enough permissions.
My python program runs a C++ program called PG_QB_Connector which calls sdktest.
Is there any way I can change the owner of the process to be a “normal” owner? Is there a better way to do this? Basically I just need to have this C++ program have eniough perms to run correctly.
BTW, when I run the C++ program by hand, the line that runs the sdktest program runs correctly, however, when I run it from the postgres/python it does not do anything...
I have Windows 7, python 3.2. The other 2 questions that I asked about this are located here and here
The python program:
CREATE or replace FUNCTION scalesmyone (thename text)
RETURNS int
AS $$
a=5
f = open('C:\\JUNK\\frompython.txt','w')
f.write(thename)
f.close()
import os
os.system('"mkdir C:\\TEMPWITHOWNER"')
os.system('"mkdir C:\\TEMPWITHOWNER\\addcustomer"')
os.system('"copy C:\\JUNK\\junk.txt C:\\TEMPWITHOWNER\\addcustomer"')
os.system('"copy C:\\BATfiles\\junk6.txt C:\\TEMPWITHOWNER\\addcustomer"')
os.system('"copy C:\\BATfiles\\run_addcust.bat C:\\TEMPWITHOWNER\\addcustomer"')
os.system('"copy C:\\Workfiles\\PG_QB_Connector.exe C:\\TEMPWITHOWNER\\addcustomer"')
os.system('"copy C:\\Workfiles\\sdktest.exe C:\\TEMPWITHOWNER\\addcustomer"')
import subprocess
return_code = subprocess.call(["C:\\TEMPWITHOWNER\\addcustomer\\PG_QB_Connector.exe", '"hello"'])
$$ LANGUAGE plpython3u;
The C++ program that is called from the python program and calls sdktest.exe is below
command = "copy C:\\Workfiles\\AddCustomerFROMWEB.xml C:\\TEMPWITHOWNER\\addcustomer\\AddCustomerFROMWEB.xml";
system(command.c_str());
//everything except for the qb file is in my local folder
command = "C:\\TEMPWITHOWNER\\addcustomer\\sdktest.exe \"C:\\Users\\Public\\Documents\\Intuit\\QuickBooks\\Company Files\\Shain Software.qbw\" C:\\TEMPWITHOWNER\\addcustomer\\AddCustomerFROMWEB.xml C:\\TEMPWITHOWNER\\addcustomer\\outputfromsdktestofaddcust.xml";
system(command.c_str());
It sounds like you want to invoke a command-line program from within a PostgreSQL trigger or function.
A usually-better alternative is to have the trigger send a NOTIFY and have a process with a PostgreSQL connection LISTENing for notifications. When a notification comes in, the process can start your program. This is the approach I would recommend; it's a lot cleaner and it means your program doesn't have to run under PostgreSQL's user ID. See NOTIFY and LISTEN.
If you really need to run commands from inside Pg:
You can use PL/Pythonu with os.system or subprocess.check_call; PL/Perlu with system(); etc. All these can run commands from inside Pg if you need to. You can't invoke programs directly from PostgreSQL, you need to use one of the 'untrusted' (meaning fully privileged, not sandboxed) procedural languages to invoke external executables. PL/TCL can probably do it too.
Update:
Your Python code as shown above has several problems:
Using os.system in Python to copy files is just wrong. Use the shutil library: http://docs.python.org/3/library/shutil.html to copy files, and the simple os.mkdir command to create directories.
The double-layered quoting looks wrong; didn't you mean to quote only each argument not the whole command? You should be using subprocess.call instead of os.system anyway.
Your final subprocess.call invocation appears OK, but fails to check the error code so you'll never know if it went wrong; you should use subprocess.check_call instead.
The C++ code also appears to fail to check for errors from the system() invocations so you'll never know if the command it runs fails.
Like the Python code, copying files in C++ by using the copy shell command is generally wrong. Microsoft Windows provides the CopyFile function for this; equivalents or alternatives exist on other platforms and you can use portable-but-less-efficient stream copying too.

Using getenv function in Linux

I have this following simple program:
int main()
{
char* v = getenv("TEST_VAR");
cout << "v = " << (v==NULL ? "NULL" : v) << endl;
return 0;
}
These lines are added to .bashrc file:
TEST_VAR="2"
export TEST_VAR
Now, when I run this program from the terminal window (Ubuntu 10.04), it prints v = 2. If I run the program by another way: using launcher or from Eclipse, it prints NULL. I think this is because TEST_VAR is defined only inside bash shell. How can I create persistent Linux environment variable, which is accessible in any case?
On my system (Fedora 13) you can make system wide environment variables by adding them under /etc/profile.d/.
So for example if you add this to a file in /etc/profile.d/my_system_wide.sh
SYSTEM_WIDE="system wide"
export SYSTEM_WIDE
and then open a another terminal it should source it regardless of who the user is opening the terminal
echo $SYSTEM_WIDE
system_wide
Add that to .bash_profile (found in your home directory). You will need to log out and log back in for it to take effect.
Also, since you are using bash, you can combine the export and set in a single statement:
export TEST_VAR="2"
Sorry if I'm being naive but isn't .bash_profile useful only if you are running bash as your default shell ?
I 'sometimes' use Linux and mostly use ksh. I have .profile so may be you should check for .*profile and export the variable there.
Good luck :)
There is no such thing as a system-wide environment variable on Linux. Every process has its own environment. Now by default, every process inherits its environment from its parent, so you can get something like a system-wide environment by ensuring that a var is set in an ancestor of every process of interest. Then, as long as no other process changes that var, every process of interest will have it set.
The other answers here give various methods of setting variables early. For example, .bash_profile sets it in every login process a user runs, which is the ultimate parent of every process they run after login.
/etc/profile is read by every bash login by every user.