John,<br><br><div class="gmail_quote">On Tue, Nov 9, 2010 at 2:18 AM, John Reid <span dir="ltr">&lt;<a href="mailto:j.reid@mail.cryst.bbk.ac.uk">j.reid@mail.cryst.bbk.ac.uk</a>&gt;</span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex;">
Hi,<br>
<br>
I&#39;m having some problems returning named tuples from a multi-engine<br>
client. I do something like:<br>
<br>
from IPython.kernel import client<br>
mec = client.MultiEngineClient()<br>
<br>
@mec.parallel()<br>
def parallel_get_starts(arg):<br>
     &lt;do some work&gt;<br>
     return &lt;some named tuples&gt;<br>
<br>
results = parallel_get_starts(&lt;some list&gt;)<br>
<br>
<br>
but I always get errors like:<br>
TypeError: __new__() takes exactly 8 arguments (2 given)<br></blockquote><div><br></div><div>Hmm, that is an odd error that I have never seen.  Even the fact that it is a TypeError is odd to me.  A couple of things to look at:</div>
<div><br></div><div>* Make sure that named tuples can be pickled and unpickled.</div><div>* See if you can come up with a super simple example that displays this error (isolate it).</div><div>* See if you can figure out where the TypeError is coming from.</div>
<div><br></div><div><br></div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex;">
whenever the results of the parallel_get_starts() function contain named<br>
tuples. I&#39;m using a namedtuple as given by Raymond Hettinger in the<br>
Python Cookbook:<br>
<a href="http://code.activestate.com/recipes/500261-named-tuples/" target="_blank">http://code.activestate.com/recipes/500261-named-tuples/</a><br>
See below.<br>
<br>
Does anyone know how I might get it to work? presumably I could move to<br>python 2.6 and use the collections.namedtuple type.<br>
<br></blockquote><div><br></div><div>It would be interesting to see if that shows the error as well.  I am wondering if the namedtuple implementation you are using has problems.</div><div><br></div><div>Cheers,</div><div>
<br></div><div>Brian</div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex;">
Thanks,<br>
John.<br>
<br>
<br>
<br>
def namedtuple(typename, field_names, verbose=False):<br>
     &quot;&quot;&quot;Returns a new subclass of tuple with named fields.<br>
<br>
     &gt;&gt;&gt; Point = namedtuple(&#39;Point&#39;, &#39;x y&#39;)<br>
     &gt;&gt;&gt; Point.__doc__                   # docstring for the new class<br>
     &#39;Point(x, y)&#39;<br>
     &gt;&gt;&gt; p = Point(11, y=22)             # instantiate with positional<br>
args or keywords<br>
     &gt;&gt;&gt; p[0] + p[1]                     # indexable like a plain tuple<br>
     33<br>
     &gt;&gt;&gt; x, y = p                        # unpack like a regular tuple<br>
     &gt;&gt;&gt; x, y<br>
     (11, 22)<br>
     &gt;&gt;&gt; p.x + p.y                       # fields also accessable by name<br>
     33<br>
     &gt;&gt;&gt; d = p._asdict()                 # convert to a dictionary<br>
     &gt;&gt;&gt; d[&#39;x&#39;]<br>
     11<br>
     &gt;&gt;&gt; Point(**d)                      # convert from a dictionary<br>
     Point(x=11, y=22)<br>
     &gt;&gt;&gt; p._replace(x=100)               # _replace() is like<br>
str.replace() but targets named fields<br>
     Point(x=100, y=22)<br>
<br>
     &quot;&quot;&quot;<br>
<br>
     # Parse and validate the field names.  Validation serves two purposes,<br>
     # generating informative error messages and preventing template<br>
injection attacks.<br>
     if isinstance(field_names, basestring):<br>
         field_names = field_names.replace(&#39;,&#39;, &#39; &#39;).split() # names<br>
separated by whitespace and/or commas<br>
     field_names = tuple(field_names)<br>
     for name in (typename,) + field_names:<br>
         if not min(c.isalnum() or c==&#39;_&#39; for c in name):<br>
             raise ValueError(&#39;Type names and field names can only<br>
contain alphanumeric characters and underscores: %r&#39; % name)<br>
         if _iskeyword(name):<br>
             raise ValueError(&#39;Type names and field names cannot be a<br>
keyword: %r&#39; % name)<br>
         if name[0].isdigit():<br>
             raise ValueError(&#39;Type names and field names cannot start<br>
with a number: %r&#39; % name)<br>
     seen_names = set()<br>
     for name in field_names<br>
         if name.startswith(&#39;_&#39;):<br>
             raise ValueError(&#39;Field names cannot start with an<br>
underscore: %r&#39; % name)<br>
         if name in seen_names:<br>
             raise ValueError(&#39;Encountered duplicate field name: %r&#39; % name)<br>
         seen_names.add(name)<br>
<br>
     # Create and fill-in the class template<br>
     numfields = len(field_names)<br>
     argtxt = repr(field_names).replace(&quot;&#39;&quot;, &quot;&quot;)[1:-1]   # tuple repr<br>
without parens or quotes<br>
     reprtxt = &#39;, &#39;.join(&#39;%s=%%r&#39; % name for name in field_names)<br>
     dicttxt = &#39;, &#39;.join(&#39;%r: t[%d]&#39; % (name, pos) for pos, name in<br>
enumerate(field_names))<br>
     template = &#39;&#39;&#39;class %(typename)s(tuple):<br>
         &#39;%(typename)s(%(argtxt)s)&#39; \n<br>
         __slots__ = () \n<br>
         _fields = %(field_names)r \n<br>
         def __new__(cls, %(argtxt)s):<br>
             return tuple.__new__(cls, (%(argtxt)s)) \n<br>
         @classmethod<br>
         def _make(cls, iterable, new=tuple.__new__, len=len):<br>
             &#39;Make a new %(typename)s object from a sequence or iterable&#39;<br>
             result = new(cls, iterable)<br>
             if len(result) != %(numfields)d:<br>
                 raise TypeError(&#39;Expected %(numfields)d arguments, got<br>
%%d&#39; %% len(result))<br>
             return result \n<br>
         def __repr__(self):<br>
             return &#39;%(typename)s(%(reprtxt)s)&#39; %% self \n<br>
         def _asdict(t):<br>
             &#39;Return a new dict which maps field names to their values&#39;<br>
             return {%(dicttxt)s} \n<br>
         def _replace(self, **kwds):<br>
             &#39;Return a new %(typename)s object replacing specified<br>
fields with new values&#39;<br>
             result = self._make(map(kwds.pop, %(field_names)r, self))<br>
             if kwds:<br>
                 raise ValueError(&#39;Got unexpected field names: %%r&#39; %%<br>
kwds.keys())<br>
             return result \n\n&#39;&#39;&#39; % locals()<br>
     for i, name in enumerate(field_names):<br>
         template += &#39;        %s = property(itemgetter(%d))\n&#39; % (name, i)<br>
     if verbose:<br>
         print template<br>
<br>
     # Execute the template string in a temporary namespace<br>
     namespace = dict(itemgetter=_itemgetter)<br>
     try:<br>
         exec template in namespace<br>
     except SyntaxError, e:<br>
         raise SyntaxError(e.message + &#39;:\n&#39; + template)<br>
     result = namespace[typename]<br>
<br>
     # For pickling to work, the __module__ variable needs to be set to<br>
the frame<br>
     # where the named tuple is created.  Bypass this step in<br>
enviroments where<br>
     # sys._getframe is not defined (Jython for example).<br>
     if hasattr(_sys, &#39;_getframe&#39;):<br>
         result.__module__ = _sys._getframe(1).f_globals[&#39;__name__&#39;]<br>
<br>
     return result<br>
<br>
_______________________________________________<br>
IPython-User mailing list<br>
<a href="mailto:IPython-User@scipy.org">IPython-User@scipy.org</a><br>
<a href="http://mail.scipy.org/mailman/listinfo/ipython-user" target="_blank">http://mail.scipy.org/mailman/listinfo/ipython-user</a><br>
</blockquote></div><br><br clear="all"><br>-- <br>Brian E. Granger, Ph.D.<br>Assistant Professor of Physics<br>Cal Poly State University, San Luis Obispo<br><a href="mailto:bgranger@calpoly.edu">bgranger@calpoly.edu</a><br>
<a href="mailto:ellisonbg@gmail.com">ellisonbg@gmail.com</a><br>