How to source a file having environment variables - python

I have a source file having environment variables (few environmental variables are conditional based as well).
source file is like (filename: global_setup)
if( -f /tools/tool/bin) then
setenv SHELL /bin/csh
endif
setenv LICENCE_FILE 2457#abc
setenv ...........
I want to source this file using python script. Code is like this:
import subprocess
import os
if os.path.isfile('global_setup'):
subprocess.call(['/bin/csh', '-c', 'source ~/global_setup'], shell=True)
else:
print("file not found");
But this is not working. Showing error as:
/home/global_setup: line 53: syntax error: unexpected end of file
Also, I tried to remove this EOF error by changing file format to Unix.
Even it works, i doubt setup will be done in some other terminal as i am using subprocess.call() in python.

Sourcing a file with subprocess.call() won't have an effect on the environment variables in Python, since subprocess runs, well, a subprocess.
You will need to parse the file yourself if you wish to affect os.environ within your Python interpreter.
Since your file is csh-style, the otherwise very nice envparse module won't do here.
Something you could do, though, is invoke
env = subprocess.check_output(['/bin/csh', '-c', 'source ~/global_setup; printenv'], shell=True)
and parse the resulting env variable line by line and add the contents into os.environ. This way the conditionals within global_setup would also work as expected.

Instead of doing it this way, you should be doing one of two things:
Source your files in the linux shell before invoking your script.
Convert your file into a dotenv file that Python can read using the Python-dotenv module.
Sourcing it before is easier IMO, instead of sourcing it during runtime using subprocess.

Related

Call a bash function within a python script

I have a python script (e.g. test.py) and a commands.txt file which contains a custom bash function (e.g. my_func) along with its parameters, e.g.
my_func arg1 arv2; my_func arg3 arg4; my_func arg5 arg6;
This function is included in the ~/.bash_profile.
What I have tried to do is:
subprocess.call(['.', path/to/commands.txt], shell=True)
I know this is not the best case, in terms of setting the shell argument into True, but I cannot seem to implement it even in this way. What I get when I run test.py is:
my_func: command not found
You will need to invoke bash directly, and instruct it to process both files.
At the command-line, this is:
bash -c '. ~/.bash_profile; . commands.txt'
Wrapping it in python:
subprocess.call(['bash', '-c', '. ~/.bash_profile; . commands.txt'])
You could also source ~/.bash_profile at the top of commands.txt. Then you'd be able to run a single file.
It may make sense to extract the function to a separate file, since .bash_profile is intended to be used by login shells, not like this.
If the first line of your commands.txt file had the correct shebang (for example #!/bin/bash) making your file executable (chmod +x commands.txt) will be enough :
subprocess.call("path/to/commands.txt")

Executable .py file with shebang path to which python gives error, command not found

I have a self-installed python in my user directory in a corporate UNIX SUSE computer (no sudo privilege):
which python
<user>/bin/python/Python-3.6.1/python
I have an executable (chmod 777) sample.py file with this line at the top of the file:
#!<user>/bin/python/Python-3.6.1/python
I can execute the file like this:
python sample.py
But when I run it by itself I get an error:
/full/path/sample.py
/full/path/sample.py: Command not found
I have no idea why it's not working. I'm discombobulated as what might be going wrong since the file is executable, the python path is correct, and the file executes if I put a python command in the front. What am I missing?
EDIT:
I tried putting this on top of the file:
#!/usr/bin/env python
Now, I get this error:
: No such file or directory
I tried this to make sure my env is correct
which env
/usr/bin/env
EDIT2:
Yes, I can run the script fine using the shebang command like this:
<user>/bin/python/Python-3.6.1/python /full/path/sample.py
Your file has DOS line endings (CR+LF). It works if you run python sample.py but doesn't work if you run ./sample.py. Recode the file so it has Unix line endings (pure LF at the end of every line).
Try using #!/usr/bin/env python as described in this post. Let the OS do the work.

command line python script run on a file in different directory

I have a script.py in /Users/admin/Desktop and I want to run this script on a file that is in /Users/admin//Desktop/folder/file.txt, without changing the present dir.
Question: what is the most efficient way to do that on command-line ? I am using the following commands and results are not as expected.
$ python script.py --script; /Users/admin/Desktop/file.txt
raise StopIteration('because of missing file (file.txt)')
StopIteration: because of missing file (file.txt)
Remove the semicolon because that will prematurely terminate the command.
Pass the correct path to the file to your program. You say it is /Users/admin/Desktop/folder/file.txt, however, your command is using /Users/admin/Desktop/file.txt (it's missing folder)
So the command should (probably) be:
$ python script.py --script /Users/admin/Desktop/folder/file.txt
If that doesn't work you will need to edit your question to show your code.

PYTHONPATH: command line calls on Windows 7

There are python scripts with command line arguments that I'd like to call from any location on my PC.
The idea is to share the corresponding package with others so they can open up a CMD window and run
python thescript.py arg1 arg2
regardless of their location.
How do I setup the python path/ PATH environment variables?
I've setup a package in site-packages, added that path to $PATH and edited PYTHONPATH to include the module directory (which includes __init__.py), but CMD won't find the relevant scripts.
python: can't open file 'thescript.py': [Errno 2] No such file or directory
Thanks.
Python does not look up scripts on some sort of path.
You have 2 options:
Use the full path:
python /path/to/thescript.py
Place the script in a directory that is on your PATH, make it executable (chmod +x thescript.py) and give it a Shebang line:
#!/bin/env python
The second option is probably preferable. On Windows, you can install pylauncher to support shebang lines; if you use Python 3.3 or newer, it is already included with your Python installation.
Another option would be to create a batch file for each script you care about, and put the batch file somewhere in your PATH, e.g. create a file called thescript.bat containing...
#echo off
the\path\to\python.exe the\path\to\thescript.py %*
...then you can just run...
thescript arg1 arg2
...which is about as terse a syntax as possible.

Starting module shell command from python subprocess module

I'm trying to run vnc server, but in order to do it first I need to run 'module load vnc'.
If I call which module in loaded bash shell then the command in not found is the PATH but in the same time it's available. It looks like the command is built-in.
In other words it looks like I need to execute two commands at once module load vnc;vncserver :8080 -localhost and I'm writing script to start it from python.
I have tried different variants with subprocess.Popen like
subprocess.Popen('module load vnc;vncserver :8080 -localhost', shell=True)
which returns 127 exit code or command not found.
subprocess.Popen('module load vnc;vncserver :8080 -localhost', shell=False)
showing
File <path>/subprocess.py line 621, in \__init__
errread, errwrite)
OSError: [Errno 2] No such file or directory.
If I specify shell=True, it executes from /bin/sh but I need it from /bin/bash.
Specifying executable='/bin/bash' doesn't help as it loads new bash shell but it starts as string but not as process, i.e. I see in ps list exactly the same command I would like to start.
Would you please advise how to do start this command from subprocess module? Is it possible to have it started with shell=False?
Environment Modules usually just modifies a couple environment variables for you. It's usually possible to skip the module load whatever step altogether and just not depend on those modules. I recommend
subprocess.Popen(['/possibly/path/to/vncserver', ':8080', '-localhost'],
env={'WHATEVER': 'you', 'MAY': 'need'})
instead of loading the module at all.
If you do insist on using this basic method, then you want to start bash yourself with Popen(['bash',....
If you want to do it with shell=False, just split this into two Popen calls.
subprocess.check_call('module load vnc'.split())
subprocess.Popen('vncserver :8080 -localhost'.split())
You can call module from a Python script. The module command is provided by the environment-modules software, which also provides a python.py initialization script.
Evaluating this script in a Python script enables the module python function. If environment-modules is installed in /usr/share/Modules, you can find this script at /usr/share/Modules/init/python.py.
Following code enables module python function:
import os
exec(open('/usr/share/Modules/init/python.py').read())
Thereafter you can load your module and start your application:
module('load', 'vnc')
subprocess.Popen(['vncserver', ':8080', '-localhost'])

Categories