0

I am calling the function load() with the following:

load(r'M:\test_3.p', marker = '*', linestyle = '-.', color = 'b', grid = True)

And within that function I am printing kwargs['color'] and I am only getting one value, I am getting the value b (the one I originally inputted in the function call) . Is there any other reason why I would get this error? There error is in the exec(plotting_string) line at the very end of the script. Can anyone help?

The error is specifically:

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "functions_mar.py", line 236, in load
    exec(plotting_string)
  File "<string>", line 1, in <module>
TypeError: plot() got multiple values for keyword argument 'color' 

The code below:

def load(string, **kwargs):   
    #Unpickling the data in order
    f = open(string, 'r')
    raw_data = pk.load(f)
    title = pk.load(f) 
    xlabel = pk.load(f) 
    ylabel = pk.load(f)
    line_labels = pk.load(f)
    line_colors = pk.load(f)
    line_marker = pk.load(f)
    f.close()    


    #Specifying the graph  
    fig0 = plt.figure()
    ax = fig0.add_subplot(1,1,1)
    plt.ion()    

    # Handles plt. methods (included some basic ones but in future will add library of all)
    if kwargs.get('title') is not None:
        plt.title(kwargs['title'])
        del kwargs['title']
    else:
        plt.title(title)
    if kwargs.get('xlabel') is not None:
        plt.xlabel(kwargs['xlabel'])
        del kwargs['xlabel']
    else: 
        plt.xlabel(xlabel)
    if kwargs.get('ylabel') is not None:
        plt.ylabel(kwargs['ylabel'])
        del kwargs['ylabel']
    else: 
        plt.ylabel(ylabel)
    if kwargs.get('grid') is not None:
        try:        
            plt.grid(kwargs['grid'])
            del kwargs['grid']
        except Exception as e:
            plt.grid(True)
            del kwargs['grid']
            print 'Error: ',e, '\n ERROR: Grid can only be BOOLEAN: True or False.'                      
    else: 
        plt.grid(True)    


    #VARIABLE ARGUMENT HANDLER     
    # Handles variable keyword arguments as to not coincide with the defaults  
    if kwargs is not None: 
           plotting_string  ='ax.plot(x,y, label = line_labels[i], color = line_colors[i], marker = line_marker, **kwargs)' 
           if kwargs.get('marker') is not None:
                   plotting_string = plotting_string.replace('line_marker', '\''+ kwargs['marker'] +'\'' )
                   del kwargs['marker']

           if kwargs.get('color') is not None:
                   if len(kwargs['color']) != len(raw_data): 
                       if len(kwargs['color']) == 1:
                           try:

                               plotting_string = plotting_string.replace('line_colors[i]', '\'' + kwargs['color']+'\'' )
                           except: 
                               print 'Color must be a string!!'
                       else:
                           print 'Must enter as many colors as there are lines'
                           del kwargs['color']  

                   else: 
                       colors  = kwargs['color'] 
                       plotting_string = plotting_string.replace('line_colors', 'colors')
                       del kwargs['color']


    #Regenerating the plot from the unpickled data     
    print kwargs['color']
    for i,line in enumerate(raw_data): 
       x = line[0]
       y = line[1]

       if kwargs is not None: 
           exec(plotting_string)
       else: # User didnt enter any additional arguments 
           ax.plot(x,y, label = line_labels[i], color = line_colors[i], marker = line_marker, **kwargs)




    plt.legend()
    plt.show()
marjak
  • 93
  • 7
  • 1
    You are passing in your `kwargs` as well as your arguments into your `plot` call so, yes, you are giving multiple values for `color` (and pretty much every other argument). I think you are misunderstanding how `kwargs` works; you should either take out `kwargs` from your `plot` call or just pass `kwargs` without passing in your explicit arguments. – R Nar Jul 18 '16 at 16:04
  • 1
    also, using `exec` is uneccesary, why not just call that line instead of calling an `exec(string)`? – R Nar Jul 18 '16 at 16:05
  • I am using exec because I manipulate the string according to what the user calls the functions with. This allows the default function call to execute, but also allows me to manipulate the function call (with string manipulations) according to what the user wants with kwargs, and execute it. – marjak Jul 18 '16 at 16:22
  • I solved the problem, I just needed to add del kwargs['color'] after doing the string replacement. Thanks @R Nar – marjak Jul 18 '16 at 16:23
  • 1
    Yes, I can see that. However, with the code and examples you are giving, it is just as easy to just call `plot(x,y, kwargs**)` and it will give the same effect. `kwargs` already packs your arguments into an object that allows you to pass in variable arguments, that's exactly what `kwargs` is for. Parsing it like you are, then mirroring the effect into a string-exec call is both [unnecessary and potentially dangerous](http://stackoverflow.com/questions/1933451/why-should-exec-and-eval-be-avoided) – R Nar Jul 18 '16 at 16:29
  • @RNar You seem to not understand what I am trying to do. If I 'just' called plot(x,y,**kwargs) it would only have the plotting properties (keyword arguments in this case) that the user specified! I have a 'default' string that I call, and depending on what the user wants additionally I do a string replacement in order to not have multiple values for keyword arguments! Using string manipulations and exec seems to be the best way to do this. if you know of any other way, please make me aware of it. – marjak Jul 19 '16 at 08:23

0 Answers0