Python subprocess.call with variable substitution - python

The Code:
MOST_POPULAR_REPORTS_LOCATION = '/tmp'
MOST_POPULAR_REPORTS_FILE = 'filename.xml'
TEMP_DATA_FILE_LOCATION = '/tmp/other_location'
subprocess.call(["/bin/cp","-a","MOST_POPULAR_REPORTS_LOCATION MOST_POPULAR_REPORTS_FILE","TEMP_DATA_FILE_LOCATION"])
What do I put between MOST_POPULAR_REPORTS_LOCATION and MOST_POPULAR_REPORTS_FILE to put a / there? I have tried various combinations without success.
What I want is to separate the two variables with a /, so that it reads /tmp/filename.xml by using variable substitution. I do not want to hardcode the paths or filenames as they are used throughout the script.

Use os.path.join:
subprocess.call(["/bin/cp", "-a",
os.path.join(MOST_POPULAR_REPORTS_LOCATION, MOST_POPULAR_REPORTS_FILE),
TEMP_DATA_FILE_LOCATION])
You should not put variable names in quotes, or you'll get string literals. This is not shell.

Related

Trouble understanding Bash and translating to Python

I am trying to translate this from Bash to Python:
export file="${directory}/scrutation_$(date "+%Y%m%d_%H%M%S").log"
I know that export sets an environment variable, and that (date "+%Y%m%d_%H%M%S") is strftime("%d/%m/%Y, %H:%M:%S") in Python.
This is what I have tried:
import os
os.environ[file]= f"{directory}/scrutation[strftime("%d/%m/%Y, %H:%M:%S")].log"
Is this correct?
The name of the environment variable is a string, it needs to be quoted.
Double quotes aren't nested in f"", use single quotes for one of the pairs.
$(...) is the Command Substitution, i.e. you need to run the strftime, not include it in square brackets.
Also, you can use the same format string without changes, unless you really want to change the timestamp format.
os.environ['file'] = f'{directory}/scrutation_' \
f'{datetime.now().strftime("%Y%m%d_%H%M%S")}.log'

Python string format

I have defined the string variable
value=“c:/program files/tm su/usr”
I need to use this variable in another string like
Bashcmd=“Override project={value}”
I tried adding the rf option like this
Bashcmd =rf“Override {value}”
But it’s printing only until c:/program, white spaces are neglected.
Is there any way to use entire path in Bashcmd and can’t remove spaces in directory path because many system share same paths.
You can format strings like this:
value="c:/program files/tm su/usr"
Bashcmd=f"Override project=\"{value}\""
or you can simply concatenate the string like this:
Bashcmd="Override project=\""+value+"\""

Control order of pathlib and string concatenation

I have a directory I want to save files to, saved as a Path object called dir. I want to autogenerate files names at that path using string concatenation.
The only way I can get this to work in a single line is just through string concatenation:
dir = Path('./Files')
constantString = 'FileName'
changingString = '_001'
path2newfile = dir.as_posix() + '/' + constantString + changingString
print(path2newfile) # ./Files/Filename_001
... which is overly verbose and not platform independent.
What I'd want to do is use pathlib's / operator for easy manipulation of the new file path that is also platform independent. This would require ensuring that the string concatenation happens first, but the only way I know how to do that is to set a (pointless) variable:
filename = constantString + changingString
path2newfile = dir / filename
But I honestly don't see why this should have to take two lines.
If I instead assume use "actual" strings (ie. not variables containing strings), I can do something like this:
path2newfile = dir / 'Filename' '_001'
But this doesn't work with variables.
path2newfile = dir / constantString changingString
# SyntaxError: invalid syntax
So I think the base question is how do I control the order of operators in python? Or at least make the concatenation operator + act before the Path operator /.
Keep in mind this is a MWE. My actual problem is a bit more complicated and has to be repeated several times in the code.
Just use parentheses surrounding your string contatenation:
path2newfile = dir / (constantString + changingString)
Have you considered using Python f-strings?
It seems like your real-world example has a "template-y" feel to it, so something like:
path / f"constant part {variable_part}"
may work.
Use os.path.join().
It's both platform-independent and you can plug the desired path parts as arguments.

Convert a dynamically generated string to raw text

I am quite new to python and i struck an issue wherein, I am dynamically retrieving a string from a dictionary which looks like this
files="eputilities/epbalancing_alb/referenced assemblies/model/cv6_xmltypemodel_xp2.cs"
I am unable to to perform any actions on this particular file as it is reading the path as 2 different strings
eputilities/epbalancing_alb/referenced and assemblies/model/cv6_xmltypemodel_xp2.cs
as there is a space between referenced and assemblies.
I wanted to know how to convert this to raw_string (ignore the space, but still keep the space between the two and consider it as one string)
I'm not able to figure this out although several comments where there on the web.
Please do help.
Thanks
From the comments to the other answer, I understand that you want to execute some external tool and pass a parameter (a filename) to it. This parameter, however, has spaces in it.
I'd propose to approaches; definitely, I'd use subprocess, not os.system.
import subprocess
# Option 1
subprocess.call([path_to_executable, parameter])
# Option 2
subprocess.call("%s \"%s\"" % (path_to_executable, parameter), shell=True)
For me, both worked, please check if they work yor you as well.
Explanations:
Option 1 takes a list of strings, where the first string has to be the path to the executable and all others are interpreted as command line arguments. As subprocess.call knows about each of these entities, it properly calls the external so that it understand thatparameter` is to be interpreted as one string with spaces - and not as two or more parameters.
Option 2 is different. With the keyword-argument shell=True we tell subprocess.call to execute the call through a shell, i.e., the first positional argument is "interpreted as if it was typed like this in a shell". But now, we have to prepare this string accordingly. So what would you do if you had to type a filename with spaces as a parameter? You'd put it between double quotes. This is what I do here.
Standard string building in python works like this
'%s foo %s'%(str_val_1, str_val_2)
So if I'm understanding you right either have a list of two strings or two different string variables.
For the prior do this:
' '.join(list)
For the latter do this:
'%s %s'%(string_1, string_2)

Python -- Quotations around filenames

I'm not quite sure when I need to put quotations around the filenames in Python.
For example, when I set
f = open(file)
I can run something like
len(f.read())
and it will run fine.
However, when I do it directly, it only works with
len(open("file").read())
Likewise, in terminal when running from Python I always have to use quotations.
What is the 'rule' when using quotations?
Thank you.
In python you can always use the name of a variable or function outside quotations, but the name of a file is usually not a variable.
If file is the name of a string variable you can always do open(file).read(), however if it is literally the filename you must always do open("file").read().
Quotations indicate a string literal constant. No quotations indicate that you're referencing a variable, which may itself be a string (in this case, populated with the path to a file).

Categories

Resources