5

payload is a comma separated chunk of data that represents the readings from an inverter. These readings need to be stored in a table called InverterHistory. There will not always be a value for each field. The model already has been setup to allow null/blank for the fields. So I am trying to check to see if there is a value present before assigning it to a field. Here is what I have so far:

i = Inverter.objects.get(mac=u)
payload.reverse()

try:
    ac_volts_a = str(payload.pop())
    ac_volts_b = str(payload.pop())
    ac_volts_c = str(payload.pop())
    ac_current_a = str(payload.pop())
    ac_current_b = str(payload.pop())
    ac_current_c = str(payload.pop())
    dc_volts = str(payload.pop())
    dc_current = str(payload.pop())
    kw_out = str(payload.pop())
    mwh_total = str(payload.pop())
    current_time  = datetime.datetime.utcnow().strftime("%Y-%m-%d %H:%M:%S")

    i_data = InverterHistory(
        inverter = i,
        if ac_volts_a: 
            voltage_ac_a = float(ac_volts_a),
        if ac_volts_b: 
            voltage_ac_b = float(ac_volts_b),   
        if ac_volts_c: 
            voltage_ac_c = float(ac_volts_c),
        if ac_current_a: 
            current_ac_a = float(ac_current_a), 
        if ac_current_b: 
            current_ac_b = float(ac_current_b),
        if ac_current_c: 
            current_ac_c = float(ac_current_c),
        if dc_volts: 
            voltage_dc = float(dc_volts),   
        if dc_current: 
            current_dc = float(dc_current), 
        if kw_out: 
            kwout = float(kw_out),
        if mwh_total: 
            mwh = float(mwh_total),
        recordTime  = datetime.datetime.utcnow().strftime("%Y-%m-%d %H:%M:%S"))
    i_data.save()
except Exception, e:
    print >> sys.stderr, "Error While Recording Inverter History"
    print >> sys.stderr, e
    raise Http404

I am fairly new to python and don't know how to properly code the above. When I try to compile the code I am getting an error where the if statements start. How can i fix the above code so it will compile and work as desired?

Rodrigue
  • 3,617
  • 2
  • 37
  • 49
Linger
  • 14,942
  • 23
  • 52
  • 79

4 Answers4

8

When you write i_data = InverterHistory(...), you are creating an object of type InverterHistory and the ... are the parameters you pass to the constructor. Constructing an object in Python is like calling a function or a method and you cannot put logic inside the parenthesis. So, you are getting an error because it is incorrect syntax to put an if statement there.

What you need to do is move your logic out of the parenthesis and put all your variables inside a Python dict. You can then pass that dict as parameter to your call to InverterHistory.

params = {
    'inverter': i,
    'recordTime': datetime.datetime.utcnow().strftime("%Y-%m-%d %H:%M:%S")
}
if ac_volts_a:
    params['voltage_ac_a'] = float(ac_volts_a)
if ac_volts_b: 
    params['voltage_ac_b'] = float(ac_volts_b)

# Do the same with all your attributes
# ...

# Then you can create your object and pass it the dictionary you have created
i_data = InverterHistory(**params)

The **params unpacks the dictionary. This means that the interpreter will take all the key: value from the dictionary and turn them into key=value. This way, each param for which the if statement was True will be passed as a named parameter to InverterHistory

Rodrigue
  • 3,617
  • 2
  • 37
  • 49
  • Using a dictionary worked great. Your answer was similar to Lycha's, however you explained it better. Thanks for the time and answer. – Linger Jul 12 '12 at 14:19
5

You should construct the argument dictionary before calling the method and then use the python keyword unpack operator to pass the dictionary as an argument.

Simplified example:

kwargs = {"inverter":i}
if ac_volts_a: 
  kwargs['voltage_ac_a'] = float(ac_volts_a)
i_data = InverterHistory(**kwargs)

Related SE question: What does *args and **kwargs mean?

Community
  • 1
  • 1
Lycha
  • 9,937
  • 3
  • 38
  • 43
1

I don't quite get what you're trying to do, but the error is because of the unmatched parenthesis two lines before the first if statement. You can't have if statements inside the list of arguments when calling a function.

Lev Levitsky
  • 63,701
  • 20
  • 147
  • 175
  • The closing parenthese is on the "recordTime = ..." line, and while you cannot have if statements, you can have x if y else z statements. – Kasapo Jul 11 '12 at 21:23
  • How does that syntax look? If there is no value would I specify null as the else portion? – Linger Jul 11 '12 at 21:26
  • 2
    ``x = some_value if some_value else None`` -- see my answer above, here's more: http://en.wikipedia.org/wiki/Ternary_operation#Python it's just like PHP's ``x = (some_condition > 0) ? value_if_true : value_if_false`` – Kasapo Jul 11 '12 at 21:27
  • @Linger Kasapo is right, but your function has to be prepared to receive `None` and handle it. – Lev Levitsky Jul 11 '12 at 21:28
  • Yeah -- Lev's right. If you can't change the InverterHistory function and it doesn't deal with None values, then you'll have to use if statements to construct your dictionary and only send in values which aren't None, assuming that the InverterHistory provides proper values if the keyword doesn't exists. @Lycha just provided an answer that demonstrates this – Kasapo Jul 11 '12 at 21:30
0

One thing -- I don't think you can say def some_func(if blah: x = 0) but you could rewrite that to be def some_func(x = 0 if blah else None). You'll be replacing if then with if then else, but it should be more amenable for the interpreter.

So this part:

 i_data = InverterHistory(
    inverter = i,
    if ac_volts_a: 
        voltage_ac_a = float(ac_volts_a),
    if ac_volts_b: 
        voltage_ac_b = float(ac_volts_b),   
    if ac_volts_c: 
        voltage_ac_c = float(ac_volts_c),
    if ac_current_a: 
        current_ac_a = float(ac_current_a), 
    if ac_current_b: 
        current_ac_b = float(ac_current_b),
    if ac_current_c: 
        current_ac_c = float(ac_current_c),
    if dc_volts: 
        voltage_dc = float(dc_volts),   
    if dc_current: 
        current_dc = float(dc_current), 
    if kw_out: 
        kwout = float(kw_out),
    if mwh_total: 
        mwh = float(mwh_total),
    recordTime  = datetime.datetime.utcnow().strftime("%Y-%m-%d %H:%M:%S"))

all the if statements are "backwards".

EDIT:

a better way might be this:

i_data = InverterHistory(**keywords)

then in the definition, you use this construct:

 def InverterHistory(**kws):
    voltage_ac_a = float(kws.get('ac_volts_a',0.00));

or

 def InverterHistory(**kws):
    voltage_ac_a = kws.get('ac_volts_a',None);
    voltage_ac_a = float(voltage_ac_a) if voltage_ac_a else None # avoids error if none
Kasapo
  • 5,294
  • 1
  • 19
  • 21