Switch to full style
Ask all general Gimp related questions here
Post a reply

Help from python experts

Sat Mar 19, 2016 9:47 am

GIMP Version: 2.8.16
Operating System: Windows
GIMP Experience: Basic Level

List any ERROR messages you received:
TypeError: object of type 'NoneType' has no len()



I'm trying to create the elementary base for a main python filter which -at a certain point- needs to get an array created by an ancillary python function.
I coded the ancillary function (as an example) as such:
Code:
#!/usr/bin/env python
from gimpfu import *

def get_array (nrc):
     
    array = []
       
    for c in range (0, int(nrc)):
        array.append(10*c) 
       
    gimp.message ("executed")
    gimp.message ("first value = "+str(array[0]))
    gimp.message ("last value = "+str(array[c]))
    gimp.message ("number of values = "+str(len(array)))
   
    return(array)

register(
    "get_array",
    "to test creating and returning an array",   
    "This script tests how creating and returning an array",
    "Diego",
    "Diego Nassetti ",
    "March 2016",
    "get_array",
    "",
    [
      (PF_ADJUSTMENT, "howmany", "how many values", 12, (4, 64, 1)),
    ],
    [],
    get_array,
    menu="<Image>/DiegoTest"
    )
main()

If called directly it display all the expected messages:
Code:
  getarray Warning
executed

  getarray Warning
first value = 0

  getarray Warning
last value = 110

  getarray Warning
number of values = 12



Then I created (again as an example) a caller as such:
Code:
#!/usr/bin/env python
from gimpfu import *
def Test_Call2 (inNr) :
   
    values = [] # values is an empty array (a list) initially
    values = (pdb.python_fu_get_array (inNr))
    c = len(values)
    gimp.message ("last value = "+str(values[c]))
   
    return()

register(
    "Test_Call2",
    "to test calling the Get_Array",   
    "This script tests how calling the Get_Array",
    "Diego",
    "Diego Nassetti ",
    "March 2016",
    "Test Call Get Array",
    "",
    [
      (PF_ADJUSTMENT, "howmany", "how many values", 12, (5, 24, 1)),

    ],
    [],
    Test_Call2,
    menu="<Image>/DiegoTest"
    )
main()


If I launch the caller I get:
- first all the messages listed above issued by the called ancillary function, then the error indicated in the "List any ERROR...", i.e. TypeError: object of type 'NoneType' has no len()

The error in the code of my caller is likely very stupid, but because I'm novice on python I cannot identify it.

Can some expert in Python tell me what is wrong in the caller (or in the return statement of the called)? Thanks a lot !

Re: Help from python experts

Sat Mar 19, 2016 11:37 am

hey,
i don't know much about the pdb.python_fu_get_array (inNr) call
but i would try to print that out first and see what it is before calling len() on it.

Re: Help from python experts

Sat Mar 19, 2016 11:51 am

trandoductin wrote:hey,
i don't know much about the pdb.python_fu_get_array (inNr) call
but i would try to print that out first and see what it is before calling len() on it.

Tin, I posted the source of python_fu_get_array, and also said that standalone it works perfectly.
The error should be either in the form of the called return (?) or in the form of getting the array from the caller.

Re: Help from python experts

Sat Mar 19, 2016 11:57 am

dinasset wrote:
trandoductin wrote:hey,
i don't know much about the pdb.python_fu_get_array (inNr) call
but i would try to print that out first and see what it is before calling len() on it.

Tin, I posted the source of python_fu_get_array, and also said that standalone it works perfectly.
The error should be either in the form of the called return (?) or in the form of getting the array from the caller.

my bad, i see the first portion of code now... it looks good to me. maybe gimp does something to the function it's returning type None and it's not iterate-able ... i am trying to debug this right now and see what it is maybe i'll learn something too ;)

Re: Help from python experts

Sat Mar 19, 2016 12:24 pm

thanks for your tests.
Note that if the code is put alltogether in a same source (having the ancillary function called via only its name without the prefix "pdb.python_fu_), the code executes correctly, that is: the caller receives the array from the called ancillary def

Re: Help from python experts

Sat Mar 19, 2016 12:48 pm

solved...

for your first portion of the code instead of
Code:
register(
    "get_array",
    "to test creating and returning an array",   
    "This script tests how creating and returning an array",
    "Diego",
    "Diego Nassetti ",
    "March 2016",
    "get_array",
    "",
    [
      (PF_ADJUSTMENT, "howmany", "how many values", 12, (4, 64, 1)),
    ],
    [],
    get_array,
    menu="<Image>/DiegoTest"
    )


use something like this to specify there's one return value of list or array.
Code:
register(
    "get_array",
    "to test creating and returning an array",   
    "This script tests how creating and returning an array",
    "Diego",
    "Diego Nassetti ",
    "March 2016",
    "get_array",
    "",
    [
      (PF_ADJUSTMENT, "howmany", "how many values", 12, (4, 64, 1)),
    ],
    [ (PF_VALUE, "return_value", "returns a list/array")
    ],
    get_array,
    menu="<Image>/DiegoTest"
    )

The below is information for people searching for how to
How to return value(s)/list with Python Fu Gimp register.
the 10th parameter of register call specifies results, if you leave this as empty list, it doesn't matter what your function returns, the return values will be ignored.
You have to specify a tuple (type,name,description) to indicate that you're returning something to the register call.

Re: Help from python experts

Sat Mar 19, 2016 1:51 pm

Many thanks Tin, I didn't know at all the "definition" of the retuned value.
That problem is solved (no more "None type"), but now the problem is that the returned value is a string of characters: first value is "[", last balue is "]", number of values (len()) is 49.
Could you solve for me also this problem? what should I put instead of "value"? (I just copied your indications)

Re: Help from python experts

Sat Mar 19, 2016 2:00 pm

i.e. how to specify in the called function that it's returning an array of integers?
or how to specify in the caller that it is receiving that string as an array of integers?

Re: Help from python experts

Sat Mar 19, 2016 2:10 pm

probably I solved it: I have to use the "split" python function (and remove the square brackets)

Re: Help from python experts

Sat Mar 19, 2016 2:17 pm

yes, in the caller I had to put:
Code:
string = (pdb.python_fu_get_array (inNr))
ls = len(string)
cleanstring = string[1:ls-1]
values = cleanstring.split(",")

very likely there is a much more elegant way to solve the problem, but the importante is to be able of getting my array of values.
Thanks again Tin !

Re: Help from python experts

Sat Mar 19, 2016 2:52 pm

I didn't find out how to pass it as an array...

so in the caller i used this eval to turn it back to a list

Code:
values = eval(pdb.python_fu_get_array (inNr))

Re: Help from python experts

Sat Mar 19, 2016 3:12 pm

thank again, Tin, much more elegant than my verbose technique!

Re: Help from python experts

Sat Mar 19, 2016 4:48 pm

http://wiki.elvanor.net/index.php/GIMP_Scripting
According to above link.
all the PF_ array types are obsolete. And they suggested using a workaround in the caller code anyways.

Obsolete:

#PF_INT8ARRAY = PDB_INT8ARRAY
#PF_INT16ARRAY = PDB_INT16ARRAY
#PF_INT32ARRAY = PDB_INT32ARRAY
#PF_INTARRAY = PF_INT32ARRAY
#PF_FLOATARRAY = PDB_FLOATARRAY
#PF_STRINGARRAY = PDB_STRINGARRAY
#PF_SELECTION = PDB_SELECTION
#PF_BOUNDARY = PDB_BOUNDARY
#PF_PATH = PDB_PATH
#PF_STATUS = PDB_STATUS

Note that you cannot currently pass an array to a Python Gimp script, since PF_STRINGARRAY has been removed (see this bug for reference). One workaround is to pass a string with special separators (like slashes), and split it into an array inside the Python code.

Re: Help from python experts

Sat Mar 19, 2016 4:50 pm

thanks for the info, in fact I tried ...ARRAY but wasn't accepted

Re: Help from python experts

Sun Mar 20, 2016 4:22 am

you made a good discovery, Tin, so far (also googling here and there) I always thought to "eval()" to a way to execute a statement, like eval(expr) where expr=1+2 and eval returns 3.
This possibility is very interesting, given the lack of arrays as parameters in Gimp PDB.
Thanks.

Re: Help from python experts

Sun Mar 20, 2016 11:06 am

dinasset wrote:you made a good discovery, Tin, so far (also googling here and there) I always thought to "eval()" to a way to execute a statement, like eval(expr) where expr=1+2 and eval returns 3.
This possibility is very interesting, given the lack of arrays as parameters in Gimp PDB.
Thanks.


eval() just evaluates whatever expression you give it..and our string for example [1,2,3] is how we express a list in code so that's why it works...str(list) in python returns a string that is identical as the code as if we were to code it so it's all good there.
Post a reply