calling bash configuration files in python script to setup environmental variables [duplicate] - python

This question already has answers here:
Emulating Bash 'source' in Python
(6 answers)
Closed 7 years ago.
I have a text file contains all the paths belong to bunch of commands that can be called in the bash scrpits and it is called progs.ini.
Usually when I want to call this configuration file in my bash script I use this command
. progs.ini
progs.ini contains stuff for instance like this:
BIN=/bin/linux_64/
P_ANALYSE=${BIN}/analyse
NPARA=1
now I want to use some part of my code in python and I was trying to use this command as following:
import subprocess as S
import os
CMD='. progs.ini'
S.call([CMD],shell=True)
It doesn't return any error message but it can not recognise the variables which are defined in progs.ini
>>os.system('echo ${BIN}')
0
Well it is not about setting some environmental variable which is similar to this problem. I want to set some variables using the configuration file.

You seem to be using Linux. In that case I would be inclined to put a cat /proc/$$/environ at the end of your ini file. That will print out all the key value pairs in a format that's easy to parse. This should do:
s = os.popen(". whatever.ini && cat /proc/$$/environ").read()
env_vars = {x[:x.find("=")]:x[x.find("=")+1:] for x in s.split("\00")[:-1]}
Tested. That didn't work but this did:
s = os.popen(". ./whatever.ini && set").read()
env_vars = {x[:x.find("=")]:x[x.find("=")+2:-1] for x in s.split("\n")[:-1]}
print env_vars['hello']

Related

Passing ipython variable to bash command one line for loop

I'm sorry for asking a duplicate as this and this are very similar but with those answers I don't seem to be able to make my code work.
If have a jupyter notebook cell with:
some_folder = "/some/path/to/files/*.gif"
!for name in {some_folder}; do echo $name; done
The output I get is just {folder}
If I do
some_folder = "/some/path/to/files/*.gif"
!for name in "/some/path/to/files/*.gif"; do echo $name; done # <-- gives no newlines between file names
# or
!for name in /some/path/to/files/*.gif; do echo $name; done # <-- places every filename on its own line
My gif files are printed to screen.
So my question why does it not use my python variable in the for loop?
Because the below, without a for loop, does work:
some_folder = "/some/path/to/files/"
!echo {some_folder}
Follow up question: I actually want my variable to just be the folder and add the wildcard only in the for loop. So something like this:
some_folder = "/some/path/to/files/"
!for name in {some_folder}*.gif; do echo $name; done
For context, later I actually want to rename the files in the for loop and not just print them. The files have an extra dot (not the one from the .gif extension) which I would like to remove.
There's an alternative way to use shell bash in a Jupyter cell with cell magic, see here. It seems to allow what you are trying to do.
If you already ran in a normal cell some_folder = r"/some/path/to/files/*.gif" or some_folder = "/some/path/to/files/*.gif", then you can try in a separate cell:
%%bash -s {some_folder}
for i in {1..5}; do echo $1; done
That said, what you seems to be trying to do with some_folder = "/some/path/to/files/*.gif" isn't going to work as such. If you try to pass "/some/path/to/files/*.gif" from Python to bash, it isn't going to work like passing /some/path/to/files/*.gif directly to bash. Bash isn't passing "/some/path/to/files/*.gif" directly to a command, it expands it and then passes it. There's not going to be an expansion passing from Python. And there's other peculiarities you'll come across. Tar you can pass a Python list of files directly using the bracket notation and it will handle that.
The solutions are to either do more on the Python side or more in the shell side. Python has it's own glob module, see here. You can combine that with working with os.system(). Python has fnamtch that is nice because you can use Unix-like file name matching. Plus there's shutil that allows moving/renaming, see shutil.move(). In Python os.remove(temp_file_name) can delete files. If you aren't working on a Windows machine there's the sh module that makes things nice. See here and here.

zsh error when executing python code as a script [duplicate]

This question already has an answer here:
Passing a url as argument
(1 answer)
Closed 2 years ago.
I have a Python script which uses sys to accept arguments -
import sys
url = sys.argv[1]
I need to provide it with a bunch of urls to parse. The script works perfectly on a jupytor notebook (after hard-coding the arguments in the code: url = 'http://www.hello.com') notebook but when I try to execute it as a script I get errors like these, for various URLs -
for 'http://www.blog.example.com:123/path/to/file.html?key1=value1'
[1] 85926
zsh: no matches found: http://www.blog.example.com:123/path/to/file.html?key1=value1
[1] + exit 1 python -m urlparser
for 'https://www.hello.com/photo.php?id=2064343443411&set=a.2634433167446&type=3&hall'
zsh: parse error near `&'
Meanwhile, the script works fine for simpler URLs like https://blog.hello.com/one/two
What could be the issue? Encoding problems?
I figured -
Have to put the arguments in quotes like - 'http://www.blog.example.com:123/path/to/file.html?key1=value1'

Passing to SOAP arguments from the command line

I have a python script that successfully sends SOAP to insert a record into a system. The values are static in the test. I need to make the value dynamic/argument that is passed through the command line or other stored value.
execute: python myscript.py
<d4p1:Address>MainStreet</d4p1:Address> ....this works to add hard coded "MainStreet"
execute: python myscript.py MainStreet
...this is now trying to pass the argument MainStreet
<d4p1:Address>sys.argv[1]</d4p1:Address> ....this does not work
It saves the literal text address as "sys.argv[1]" ... I have imported sys ..I have tried %, {}, etc from web searches, what syntax am I missing??
You need to read a little about how to create strings in Python, below is how it could look like in your code. Sorry it's hard to say more without seeing your actual code. And you actually shouldn't create XMLs like that, you should use for instance xml module from standard library.
test = "<d4p1:Address>" + sys.argv[1] + "</d4p1:Address>"

How could I get the command line that I entered in the terminal to run a python file?

Suppose I have a python file main.py, and it has some optional parameters, --learning-rate, --batch-size, and etc.
If I want to run this file, I can input the following into the terminal(Ubuntu Linux for example).
python3 main.py --learning-rate 0.1 --batch-size 100
And now, I want to write some code in main.py, in order that after I enter the command above, I can get this command in a string by executing those code. The following is the string I want to get:
"python3 main.py --learning-rate 0.1 --batch-size 100"
The reason I want to do this is that I want to write this string into my recording file so that I can know better what command I have run.
Could anyone tell me what package should I import and what code should I write to get that command information during running the python file?
Thanks!
You cannot always get precisely what you typed, because the shell will have first done substitutions and expanded filenames before starting your script. For example, if you type python "foo.py" *.txt, your script won't see *.txt, it will see the list of files, and it won't see the quotes around foo.py.
With that caveat out of the way, the sys module has a variable named argv that contains all of the arguments. argv[0] is the name of the script.
To get the name of the python executable you can use sys.executable.
To tie it all together, you can do something like this:
print(sys.executable + " " + " ".join(sys.argv))
Why not just remake the command using the arguments you parsed? It won't be exactly what you typed, but that might be nice as it will be in a common format.
Ex (assuming the learning rate and batch size are stored in similarly named variables):
command = "python3 main.py --learning-rate {} --batch-size {}".format(learning_rate, batch_size)
Of course it will be a little more complicated if some commands are optional, but I assume in that case there would be a default value for these parameters, since your network would need those parameters every time.

Accessing a python script in a different folder, using a python script

Can a python script located in D:\Folder_A\Folder_B\be used to change variables in another python script located in D:\Folder_A\Folder_C\, and then print them out on the console?
NOTE: I'm a beginner in Python, and I'm using v2.7.8.
EDIT: To answer #Rik Verbeek, I created a python file in location A (D:\Folder_A\Folder_B\), and another file at location B (D:\Folder_A\Folder_C\), with both the folders (Folder_B & Folder_C) located in D:\Folder_A\. In the 2nd .py file, I wrote the following:
a = 0
b = 0
Now I want to change these variables from the 1st .py file to 5 and 10 respectively, and print them to the console. Also, these files are not in the Python libraries, but are instead, located in another folder(Folder_A).
To answer #Kasra (and maybe #cdarke), I don't want to import a module, unless it is the only way.
If you have some "global" variables I think is a good idea to have them in a separated module and import that module from each place you need them. This way you only have to do it as cdarke has commented.

Categories