String indices must be integers, new to python - python

I hope I won't get trashed for this question. This is my first day with Python and all I've done so far is copy pasting and deducing from other snippets of code. I have no experience with code. I'm trying my hardest however this one I can't get past for the past few hours.
I'm currently adjusting an Editorial (iOS app) workflow to fit my needs — namely: posting to my WordPress site, including the ability to choose from a list of all possible post formats (I have "standard" and "link" enabled).
Here is the faulty bit from the relevant Python script:
console.show_activity('Fetching formats...')
server = xmlrpclib.ServerProxy(wp_url)
format = server.wp.getPostFormats(wp_blogid, wp_username, wp_password, 'post_format')
i = 0
for x in format:
formats += '\n' + x['name'] + " " + str(i)
i = i+1
workflow.set_variable("formats", formats)
console.hide_activity()
I'm getting the error: "string indices must be integers, not str"
What is this supposed to do is later show me in a list my available formats. I've done this successfully with server.wp.getPostFormats(wp_blogid, wp_username, wp_password, 'post_tag') and server.wp.getTerms(wp_blogid, wp_username, wp_password, 'category')
I know my problem is where the line with the i starts, I just have no idea how to solve it. I'm assuming by reading other topics that I need to cast, but I'm not even sure what getPostFormats returns, or how to do that.
Thanks in advance!
Edit: I've now concluded that server.wp.getPostFormats returns a dictionary, but I have not a slightest idea on how to retrieve only one set of data (either the key or value) of this dictionary. Please help.

You're getting that error because "string indices must be integers, not str".
formats += '\n' + x['name'] + " " + str(i)
Here, you are accessing the 'name'th element of x, where 'name' is of course a string and x is a string too, since server.wp.getPostFormats obviously returns a list of strings.
So simply look at format and you should immediately see how to obtain the required data.
UPDATE:
OK, so you figured out that format is a dictionary (returned from server.wp.getPostFormats). In Python, if you iterate over a dictionary (your for-loop), you iterate through its keys. This is the standard behaviour.
Look at this example:
>>> foo = {'a': 1, 'c': 3, 'b': 2}
>>> for x in foo: print(x)
...
a
c
b
Of course you also need the values, not only the keys (you seem to look for an entry with the key name). One way is to iterate though the keys and items in one shot:
>>> for key, value in foo.iteritems():
... print(key + ":" + str(value))
...
a:1
c:3
b:2
So the .iteritems() method of a dictionary returns for every iteration a key/value-pair, which you can unpack within the for loops definition.
In your case, you can do the following:
for key, value in format.iteritems():
formats += 'key: ' + key + ', value: ' + value + '\n'

Given that you are new, I would also suggest using the enumerate method and refactoring your code:
for i, x in enumerate(format):
formats += '\n' + x[idx_for_name] + " " + str(i)
The idx_for_name would be the index for the name.
If you wanna go even further, you can use the join method too:
formats = '\n'.join(x[idx_for_name] + " " + str(i) \
for i, x in enumerate(format))
warning: This code is untested.

Read:
http://python-wordpress-xmlrpc.readthedocs.org/en/latest/ref/methods.html#wordpress_xmlrpc.methods.posts.GetPostFormats
GetPostFormats return a dictionary so x iterates among the keys which are strings.
Try:
x= format['all']:

Related

Iterating a conversion of a string to a float in a scripting file when parsing an old file

I am using a new script (a) to extract information from an old script (b) to create a new file (c). I am looking for an equal sign in the old script (b) and want to modify the modification script (a) to make it automated.
The string is
lev1tolev2 'from=e119-b3331l1 mappars="simp:180" targ=enceladus.bi.def.3 km=0.6 lat=(-71.5,90) lon=(220,360)'
It is written in python 3.
The current output is fixed at
cam2map from=e119-b3331l1 to=rsmap-x map=enc.Ink.map pixres=mpp defaultrange=MAP res=300 minlat=-71.5 maxlat=90 minlon=220 maxlon=360
Currently, I have the code able to export a string of 0.6 for all of the iterations of lev1tolev2, but each one of these is going to be different.
cam2map = Call("cam2map")
cam2map.kwargs["from"] = old_lev1tolev2.kwargs["from"]
cam2map.kwargs["to"] = "rsmap-x"
cam2map.kwargs["map"] = "enc.Ink.map"
cam2map.kwargs["pixres"] = "mpp"
cam2map.kwargs["defaultrange"] = "MAP"
**cam2map.kwargs["res"] = float((old_lev1tolev2.kwargs["km"]))**
cam2map.kwargs["minlat"] = lat[0]
cam2map.kwargs["maxlat"] = lat[1]
cam2map.kwargs["minlon"] = lon[0]
cam2map.kwargs["maxlon"] = lon[1]
I have two questions, why is this not converting the string to a float? And, why is this not iterating over all of the lev1tolev2 commands as everything else in the code does?
The full code is available here.
https://codeshare.io/G6drmk
The problem occurred at a different location in the code.
def escape_kw_value(value):
if not isinstance(value, str):
return value
elif (value.startswith(('"', "'")) and value.endswith(('"', "'"))):
return value
# TODO escape the quote with \" or \'
#if value.startswith(('"', "'")) or value.endswith(('"', "'")):
# return value
if " " in value:
value = '"{}"'.format(value)
return value
it doesn't seem to clear to me, but from you syntax here :
**cam2map.kwargs["res"] = float((old_lev1tolev2.kwargs["km"]))**
I'd bet that cam2map.kwargs["res"] is a dict, and you thought that it would convert every values in the dict, using the ** syntax. The float built-in should then be called in a loop over the elements of the dict, or possible a list-comprehension as here :
cam2map.kwargs["res"] = dict()
for key, value in old_lev1tolev2.kwars["res"].items():
cam2map.kwargs["res"][key] = float(value)
Edit :
Ok so, it seems you took the string 'from=e119-b3331l1 mappars="simp:180" targ=enceladus.bi.def.3 km=0.6 lat=(-71.5,90) lon=(220,360)'
And then thought that calling youstring.kwargs would give you a dict, but it won't, you can probably parse it to a dict first, using some lib, or, you use mystring.split('=') and then work your way to a dict first, like that:
output = dict()
for one_bit in lev_1_lev2.split(' '):
key, value = one_bit.split('=')
output[key] = value

Get selected node names into a list or tuple in Nuke with Python

I am trying to obtain a list of the names of selected nodes with Python in Nuke.
I have tried:
for s in nuke.selectedNodes():
n = s['name'].value()
print n
This gives me the names of the selected nodes, but as separate strings.
There is nothing I can do to them that will combine each string. If I
have three Merges selected, in the Nuke script editor I get:
Result: Merge3
Merge2
Merge1
If I wrap the last variable n in brackets, I get:
Result: ['Merge3']
['Merge2']
['Merge1']
That's how I know they are separate strings. I found one other way to
return selected nodes. I used:
s = nuke.tcl("selected_nodes")
print s
I get odd names back like node3a7c000, but these names work in anything
that calls a node, like nuke.toNode() and they are all on one line. I
tried to force these results into a list or a tuple, like so:
s = nuke.tcl("selected_nodes")
print s
Result: node3a7c000 node3a7c400 node3a7c800
s = nuke.tcl("selected_nodes")
s2 = s.replace(" ","', '")
s3 = "(" + "'" + s2 + "'" + ")"
print s3
Result: ('node3a7c000', 'node3a7c400', 'node3a7c800')
My result looks to have the standard construct of a tuple, but if I try
to call the first value from the tuple, I get a parentheses back. This
is as if my created tuple is still a string.
Is there anything I can do to gather a list or tuple of selected nodes
names? I'm not sure what I am doing wrong and it seems that my last
solution should have worked.
As you iterate over each node, you'll want to add its name to a list ([]), and then return that. For instance:
names = []
for s in nuke.selectedNodes():
n = s['name'].value()
names.append(n)
print names
This will give you:
# Result: ['Merge3', 'Merge2', 'Merge1']
If you're familiar with list comprehensions, you can also use one to make names in one line:
names = [s['name'].value() for s in nuke.selectedNodes()]
nodename = list()
for node in nuke.selectedNodes():
nodename.append(node.name())

Python / json.load gives exception

I have the following line:
BL: {version: 2, revision: 1}
I want to parse it, so that I will get in one variable BL, and on the other, I will get
[[version, revision], [2,1]]
I have the following code:
for line in file:
print line.split(':',1)[0]; gives me the first word (BL)
print line.split(': ',1)[1]
data = json.loads(json.dumps(line.split(': ',1)[1]));
The problem is that data is not contained the data as variable, so when I do data[0], I get the char: {
What the correct way to do that?
Your JSON is not valid since it's keys are not valid (you probably want strings there).
To get around it you could do something hacky like:
# give value to non-string keys, to use in eval
version = "version"
revision = "revision"
d = eval(line.split(": ", 1)[1])
print [d.keys(), d.values()]
This requires you to know all keys in advance.
I recommend you fix your input-generating script instead.
I always avoid eval.

Writing txt-file float

Now I have this kind of code:
for s,h,v,r in zip(lopullinen, yksilo, osallistumiset, pistemaarat):
tulostuksia.write(str(s) + ";".join(h) + ";" + str(r) + ";" + ";".join(str(v)) + "/7" + "\n")
and it gives this kind of output:
tunnus;nimi;sarja;juoksu-60m;pituushyppy;kuulantyonto;korkeushyppy;aitajuoksu-60m;seivashyppy;juoksu-1000m;kokonaispisteet;lajeja
101;Vertti Veteraaniurheilija;M70;709;651;750;806;850;759;801;5326;7/7
41;Severi Seitsenottelija;M;603;551;600;555;559;655;700;4223;7/7
42;Seppo Seitsenottelija;M;661;750;700;610;505;502;700;4428;7/7
43;Ylermi Yleisurheilija;M;603;601;700;655;661;555;500;4275;7/7
60;K. Keskeyttäjä;M40;603;601;-;-;-;-;-;1204;2/7
61;Yrjänä Yleisurheilija;M40;559;500;650;701;603;655;650;4318;7/7
But I would like to have those numbers to be float-types. Like this:
101;Vertti Veteraaniurheilija;M70;709.0;651.0;750.0;806.0;850.0;759.0;801.0;5326;7/7
Thouse numbers come from the list yksilo, which contains numbers from class. If i change it there to be float(when adding to the list), and from that for loop above ";".join(str(h)). It gives me output where the ";" is between every number(7;0;9;.;0; etc...) And if i don't put the str(h) in there, it gives "TypeError: sequence item 0: expected str instance, float found".
Is there an easy way to get those numbers to be formed 709.0 instead of 709.
Use
'%f' % value
instead of the simple
str(value)
But the str(value) should already have given you '4.0' if the value had been a float in the beginning. So maybe you need to convert that value to a float first:
str(float(value))
Also, if you need to keep the - values, you will have to check for these as well. So in your example, use
tulostuksia.write(
'%s%s;%s;%s%s' % (
s,
";".join(h),
r,
";".join('-' if vi == 'i' else str(float(vi)) for vi in v),
"/7\n")
If h is a list [709.0, 651.0] then str(h) gives you "[709.0, 651.0]" and ';'.join(str(h)), as you've seen, will iterate over the characters in the string, rather than the values in the list.
Instead, try ';'.join(map(str, h)). This converts each item in the list individually to a string (whether it's a '-' or a float), then joins the resulting iterable/list (depending on Python version) of strings.
Example:
>>> print(";".join(map(str, ["-", 123.4, 567.8, "-", "-", 9.0])))
-;123.4;567.8;-;-;9.0

listproperty GAE to string method

So my problem below is that when it sends the json object lets say I have multiple items in the lists? well it sends that many objects except changing that field once in the dict that i created above. For some reason , even though I use the for loops above to create a string from the list it doesn't actually make it so and i get 15 objects instead of 1 object with maybe a field that has 15 things in it separated by commas.
my expected output should be
name,special1,special2,special3..etc, review1,review2
instead i get
name,special1,review1
name,special2,review1
name,special3,review1
etc..
name,special1,review2
name,special1,review3
My main question is how do I convert the list to an array or even just to a string(like a toString Method) so that my json dump doesn't spit out multiples?
class store(db.Model):
mykey = db.StringProperty(db.Key)
storeSpecial = db.ListProperty(item_type=str)
reviews = db.ListProperty(item_type=str)
storeName = db.StringProperty()
#later in the code
qy1 = GqlQuery("SELECT storeName,storeSpecial,reviews FROM store WHERE mykey =:1",dataInput)
records_to_send = []
for i in qy1:
rev =""
for k in i.review:
rev = rev + str(k) + ","
spec = ""
for k2 in i.storeSpecial:
spec = spec + str(k2) + ","
output = {"store name": i.storeName,"specials": spec,"reviews":rev}
records_to_send.append(output)
self.response.out.write(json.dumps(records_to_send))
I'm not really sure what you want, your example is confusing. If you use JSON, why not just keep it as list? Why do you change it to a string?
It seems you want something like this
for store in qy1:
records_to_send.append({'store name': store.storeName, 'specials': store.storeSpecial}, 'reviews': store.reviews})

Categories

Resources