Bug when return iterable with one element
Opened this issue · 6 comments
Hi, I encounter problem :
def test_bug_0():
return {"A": 0, "B": 1}
def test_bug_1():
return {"A": 0, "B": 1, "C": 2}
def test_bug_2():
return {"A": {0: 42, 1: 21}, "B": 1, "C": 2}
def test_bug_3():
return {"A": {0: 42, 1: 21}}
def test_bug_4():
return {"A": {0: 42}, "B": {1: 21}}
test_bug_3()
bug and return :
Traceback (most recent call last):
File "c:\users\artzetsi\miniconda2\envs\develop\lib\site-packages\openalea.core-2.0.2-py2.7.egg\openalea\core\algo\dataflow_evaluation.py", line 227, in eval_vertex_code
ret = node.eval()
File "c:\users\artzetsi\miniconda2\envs\develop\lib\site-packages\openalea.core-2.0.2-py2.7.egg\openalea\core\node.py", line 654, in eval
self.outputs[0] = outlist[0]
KeyError: 0
Worst with a collection.defaultdict like :
def test_bug_5():
d = collections.defaultdict(dict)
d["A"][0] = 42
return d
don't throw error; just return a empty dict {}
Same for you ?
Hi Simon,
A node in visualea return several arguments: a tuple.
The problem comes from when you return an iterable with one element.
Do you want to return the first element of the iterable or the iterable itself.
To solve this problem (Python has exactly the same ambiguity), you have to return a tuple of one element:
def test_bug_3(): return {"A": {0: 42, 1: 21}},
Add a coma at the end of your expression
Do you want to return the first element of the iterable or the iterable itself
I want return the iterable itself
you have to return a tuple of one element
Ok, thanks that works !
So, it's still a limitation/problem to wrap external code (= not modifiable) who return iterable with one element ? It is resolvable ?
In Python to create a tuple with one element, you have to do:
my_tuple = 1,
Because otherelse mytuple is an int of value 1. Even if you do:
my_tuple=(1)
We have exactly the same problem and there is no simple solution
Ok, but the thing a don't understand, I return a dict not a tuple. Even with a defaultdict, list or numpy array.
def defaultdict_one_element():
d = collections.defaultdict(int)
d["A"] = 42
return d
> 0
def dict_one_element():
return {"A": 42}
> key error 0
def list_one_element():
return [42]
> 42 and not [42]
def numpy_on_element():
return numpy.array([42])
> 42 and not array([42])
So openalea can't transform/wrap (=make a node) correctly a iterable with one element if they not return like a tuple of one element. It's still a huge limitation, scikit-image, scikit-learn, opencv, etc. don't return systematically (even practically never) their numpy_array/list/dict like a tuple of one element.
So, more, I try "the tuple of one element" solution. But I don't understood that changed my type of return during the python execution.
def list_one_element():
return [42],
Through visualea return the list [42]
otherwise with classic python execution the tuple ([42],)
In fact, in visualea, the default behavior is several outputs.
If the number of outputs is not define (in our case we use a Python function), then there is a problem between
- a iterable of one element
- the element of the iterable
In our case, list, tuple, dict are considered as iterable.
We have the same case in Python:
- How to differentiate a tuple of one element?
(1) is not similar to (1,)
Possible solutions
- Create a node explicitly (from the class Node) with an eval function (eg here)
- Add a decorator of a given function for functions with one output that return a list
- Use Python 3 Annotations to improe the export of functions as OpenAlea components