Python subprocess module: How can I pass comma separated input into Popen? - python

I have a list of strings and a command I'd like to run with Popen. The command takes the strings as input arguments.
How can I easily add the entire list...
list=['asdf','qwer','zxcv',...]
...as comma separated input shown below:
Popen(['cmd','asdf','qwer','zxcv',...])
I won't be able to do this because it won't convert list to str implicitly:
Popen(['cmd',list])
Nor this, because it simply won't allow for spaces within a string:
Popen(['cmd',' '.join(list)])
Is there an alternative?
I do not want to use the 'shell=True' option.

You can do the following to create a new list from two (or more) separate lists.
['cmd'] + list
This creates a new list for you with the contents of both. As you mentioned, the syntax looks and does exactly as you expect, which is adding two lists together.
Note: I would also like to warn that you shouldn't use list as a variable name. Since this means you are shadowing the built-in list type. Which could cause unforeseen problems later.

Related

Removing a single quotes from an output tuple

I'm working to create a tuple in Python in the following way:
tuple = (the_schema['fields'][i]['name'],the_schema['fields'][i]['type'])
and am getting the output ('stn', 'str').
My desired output is ('stn', str), where the second element of the tuple doesn't have the single quotes.
When I print (the_schema['fields'][i]['type']), I get str as desired. The issue, as I understand, is that Python automatically formats the tuple with quotations. How can I remove the quotation? I have tried the .replace() and .strip() methods, as well as something similar to ",".join([str(s) for s in list(k)]).
From python 3.6 on, you can use f-strings to create strings using variables, and that is quite easy to do.
Here, for your output you could use:
string_tuple = f"('{the_schema['fields'][i]['name']}', {the_schema['fields'][i]['type']})"

Python strips quotation marks when using os.getenv

I'm having difficulty with different string arrays. Previously, there were string arrays only in properties files. Currently, the system has string arrays in properties files and set as environmental variables in the user's .bashrc file. The string arrays look like the following in both the properties and .bashrc files.
STRING_ARRAY="host1","host2","host3"
Previously, there was a simple pair of for loops that read a series of these string arrays and passed them into some function.
for k in ("STRING_ARRAY","SOME_OTHER_ARRAY"):
globals()[k] = globals()[k].replace("\"",'').split(",")
for stringarray,otherarray in zip(STRING_ARRAY, SOME_OTHER_ARRAY):
someFunction(stringarray,otherarray)
This worked fine. The problem arose when some of the variables were moved out of properties files that were passed into the python script and into environmental variables. It seems that when using either os.getenv("HOSTSTRINGARRAY") or os.environ["HOSTSTRINGARRAY"], the os library returns the array of strings without the accompanying quotation marks so
PROPERTIES_STRING_ARRAY="host1","host2","host3"
print PROPERTIES_STRING_ARRAY
returns
"host1","host2","host3"
whereas
ENV_VAR_STRING_ARRAY="host1","host2","host3"
print os.getenv("ENV_VAR_STRING_ARRAY")
returns
host1,host2,host3
This is a problem because I can't seem to mix and match the two types of variables as follows
for k in ("POPERTIES_STRING_ARRAY",os.getenv("ENV_VAR_OTHER_ARRAY")):
globals()[k] = globals()[k].replace("\"",'').split(",")
for stringarray,otherarray in zip(STRING_ARRAY, os.getenv("ENV_VAR_OTHER_ARRAY")):
someFunction(stringarray,otherarray)
So my question is, how do get os.getenv or os.environ to return a comma separated list of strings without stripping off the quotations marks enclosing the individual strings?
Use ' single quote to declare the string. It should work now.
ENV_VAR_STRING_ARRAY='"host1","host2","host3"'

I need to convert a list; which will be provided through input, hence it will become a string; back into a list

As said in the title of the thread.
Also I tried using eval() for these lists I'll be inputting, but these lists contain string elements and other (sub-?) lists, e.g:
[Pacific, [-45,30,25], [120,59, 15]]
When providing such input eval() responds perfectly fine for numbers-only lists but when applied to strings sends back a NameError for these string elements saying they are not defined.
you need to be inputting your strings within quotations, ie,
["Pacific", [-45,30,25], [120,59, 15]]
when you input it just as Pacific, python's eval() function will look for a variable named Pacific, hence the NameError you have been getting
Your original input string is perfectly valid YAML string, which is a safe, powerful and -at least in my view- easy way to serialize and de-serialize data structures. In order to read (or save) YAML strings you might want to get PyYAML:
sudo pip install pyyaml
Then, you can perfectly run the following code in order to read your data into Python:
from yaml import load
pacific = load('[Pacific, [-45,30,25], [120,59, 15]]')

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)

Simulate normalizing arguments

If you pass string like this to your python as program argument
my.py name1=abc name2='def' name3="ghi klm"
then sys.args will return list like this
['name1=abc', 'name2=def', 'name3=ghi klm']
thus all quotes are considered and removed. Which function in python can take string of arguments and return such normalized list?
Update
Input string -> 'name1=abc name2=\'def\' name3="ghi klm"'
Output list -> ['name1=abc', 'name2=def', 'name3=ghi klm']
To split arguments in the same way as the shell, you can use shlex.split():
>>> shlex.split("name1=abc name2='def' name3=\"ghi klm\"")
['name1=abc', 'name2=def', 'name3=ghi klm']
Which function in python can take string of arguments and return such normalized list?
There may be one, but the work is actually done by your operating system. The Python interpreter just propagates the list it gets from the OS as sys.args.

Categories

Resources