5

I have an extensive program that is running on my server. The line with the error looks like the following:

result[0].update(dictionary)

result[0] looks like ("label",{key:value,...}) so I got an error saying that a tuple does not have update

when I fixed it to be result[0][1].update(dictionary), I got the same error!

I then added print "test" above to see what happened, and I got the same error, but it gave me the error occurring at the print statement. This tells me that the code the server is running is the original and not the edited one. I tried restarting the server. I have saved my code. I do not understand why nor how this is happening. What could be causing this and how can I make it so that the server recognizes the newer version?

error message

Traceback (most recent call last):
  File "/usr/local/lib/python2.7/dist-packages/background_task/tasks.py", line 160, in run_task
    tasks.run_task(task.task_name, args, kwargs)                                                                                                      [2/1832]
  File "/usr/local/lib/python2.7/dist-packages/background_task/tasks.py", line 45, in run_task
    task.task_function(*args, **kwargs)
  File "/.../proj/tasks.py", line 10, in automap_predict
    automap_obj.predict()
  File "/.../proj/models.py", line 317, in predict
    prediction = predictions[1]
  File "/.../proj/models.py", line 143, in predict
    #this is a recursive call
  File "/.../proj/models.py", line 143, in predict
    #this is a recursive call
  File "/.../proj/models.py", line 127, in predict
    #result[0].update(dictionary) this happens at the base case of the recursion
AttributeError: 'tuple' object has no attribute 'update'

notice that I am getting this error on a line that is commented out. Displaying that this is not the code that is really running.

view

def view(request,param):
    run_background_task(param)
    return redirect("project.view.reload")

background_task

@background(schedule=0)
def run_background_task(param):
    obj = MyModel.objects.get(field=param)
    obj.predict()

predict function

This is where the result gets created. I am not permitted to show this code, but note that I am sure that the actual code is irrelevant. It was working. I changed it to make a quick update. I got an error. I then fixed the error, but proceeded to get the same error. I even went back to the old version that was working and I still get the same error. Therefor this error has nothing to do with the contents of this function.

Let me know if I can be of any more help.

Ryan Saxe
  • 17,123
  • 23
  • 80
  • 128
  • Assuming Python 2, what does `print type(result[0])` return? – Brandon Taylor Jan 16 '15 at 18:56
  • I tried that. I don't get a result because it is running the older version of the program and therefor any edits are not run – Ryan Saxe Jan 16 '15 at 18:58
  • 1
    Have you tried deleting all of the `.pyc` files, if any? – Brandon Taylor Jan 16 '15 at 19:01
  • I have never done that before. Note that this is inside a function in a `Manager` in `models.py`...would deleting `models.pyc` be problematic? – Ryan Saxe Jan 16 '15 at 19:03
  • `.pyc` files are just the byte-code compiled Python files of the same name. On rare occasion, these files won't get regenerated at runtime when a Python file changes. The `models.pyc` file will be re-generated as soon as your code is run. It's perfectly fine to delete it. – Brandon Taylor Jan 16 '15 at 19:05
  • I just deleted it and reran with the edited code and it still executed the original version – Ryan Saxe Jan 16 '15 at 19:08
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/68979/discussion-between-brandon-and-ryan-saxe). – Brandon Taylor Jan 16 '15 at 19:08
  • Unlike forum sites, we don't use "Thanks", or "Any help appreciated", or signatures on [so]. See "[Should 'Hi', 'thanks,' taglines, and salutations be removed from posts?](http://meta.stackexchange.com/questions/2950/should-hi-thanks-taglines-and-salutations-be-removed-from-posts). BTW, it's "Thanks in advance", not "Thanks in advanced". – John Saunders Jan 17 '15 at 05:50
  • Can you post your code and full error message? If `result` is what you say it is, you shouldn't get this error. The bug might be somewhere else. – Håken Lid Jan 22 '15 at 23:17
  • I will post the error message. As far as the code is concerned, that is irrelevant as it is not running the code I want it to. The error is coming from a previous version of this code, and then I fixed what was wrong and it is not running the edited version. I am not permitted to publish the code here – Ryan Saxe Jan 22 '15 at 23:36
  • I have added what I can @HåkenLid – Ryan Saxe Jan 22 '15 at 23:44
  • 1
    Are you sure the file path is correct, and that you aren't working in a different virtualenv? Have you restarted the wsgi server? – Håken Lid Jan 22 '15 at 23:56
  • 100% sure I am in the correct place. This is not a virtual environment, this part of a used tool for my company right now, and everything is set up properly as it was working fine before I made that quick edit. I have restarted the server and the same thing happens. – Ryan Saxe Jan 22 '15 at 23:59
  • What server daemon are you using? How did you restart it? – Seán Hayes Jan 23 '15 at 03:08
  • I am running my view off of the built in `runserver` with django. so I closed it and started a new one. Is that not what was meant by restart the wsgi server? – Ryan Saxe Jan 23 '15 at 07:28

7 Answers7

12

If you are running a development server provided with django, namely ./manage.py runserver you should not experience this problem, since it automatically recompiles upon .py file saving. But if you are running wsgi say with apache server it is a common issue, but with a very simple solution. Basically what happens, whenever you change a .py file, server will still use a previously compiled python file. So solution is either restart apache sudo service apache2 restart (which is an overkill) or simply run touch wsgi.py, wherever your wsgi.py is located within a project, which will tell it to recompile .py files. Of course you can also delete the .pyc files, but that is too tedious.

Edit:

I just notice that you are using @background decorator, which make me believe you are using django-background-task. If that's the case, you will have to make sure this app actually takes your code changes into account too, which may not happen automatically while recompiling python files using touch wsgi.py approach. I don't have experience with this particular app, but for example with celery, which is a lot more sophisticated app for scheduling tasks, you would also have to restart the worker in order to reflect the changes in code, since worker actually stores a pickled version of the code.

Now after checking out the django-background-task app (which seems like the one you are using), in theory you should't have to do anything special, but just to make sure you can clear out any scheduled tasks and reschedule them again. I haven't tried but you should be able to do it through ./manage.py shell:

>>> from background_task.tasks import tasks
>>> tasks._tasks = {}

And probably you'll even have to clear out the db, for the DBTaskRunner:

>>> from background_task.models import Task
>>> Task.objects.all().delete()
lehins
  • 9,642
  • 2
  • 35
  • 49
  • +1 Touching the wsgi file was the only way I was able to solve this problem in Django somewhat elegantly. To implement touch in Python (without using a system command) see https://stackoverflow.com/questions/1158076/implement-touch-using-python – Jesuisme Feb 22 '20 at 20:12
1

May be this is what you are looking for?

result = (
        ("item1",{'key1': 'val1'}),
        ("item2",{'key2': 'val2'}),
    )
    my_dict = {
        'key1': 'updated val',
        'new key': 'new value'
    }
    pprint.pprint(result[0])    # Result: ('item1', {'key1': 'val1'})
    key, dct = result[0]    
    dct.update(my_dict)
    pprint.pprint(result)       # Result: (('item1', {'key1': 'updated val', 'new key': 'new value'}), ('item2', {'key2': 'val2'}))
Du D.
  • 5,062
  • 2
  • 29
  • 34
  • this is what I was trying to do, but was not working. The issue is not with the code, it is with the server. – Ryan Saxe Jan 23 '15 at 16:36
1

The issue may be related to compiled python files or ".pyc" files located in your project folder on your server. These files are automatically generated as the python code is interpreted. Sometimes these files aren't re-compiled even if new code is present and it keeps running the old code.

You can install "django-extensions" via pip and it comes with a handy manage.py command that can help you clear those files:

python manage.py clean_pyc

If that doesn't work then you need to restart your wsgi server that's running the code since the python code is in memory.

Alex Carlos
  • 882
  • 5
  • 7
1

If the code is not updating, solution will depend on how you are serving your application. If you are using ./manage.py runserver, you should not be having problems. Also if serving with apache + mod_python if you restart the sever the code should be reloaded.

But I assume you are not doing either of them, since you still have this problem. If your using uWSGI or gunicorn, they runs in a separate processes from the server, you would need to restart them separately. uWSGI can be set up also to reload the app every time its setting file changes, so normally I just call touch myapp.ini to reload the code.

Michael Buckley
  • 591
  • 4
  • 14
1

Basically what happens, whenever you change a .py file, server will still use a previously compiled python file. So solution is either restart apache sudo service apache2 restart (which is an overkill) or simply run touch wsgi.py, wherever your wsgi.py is located within a project, which will tell it to recompile .py files. Of course you can also delete the .pyc files, but that is too tedious.

You are using @background decorator, which make me believe you are using django-background-task. If that's the case, you will have to make sure this app actually takes your code changes into account too, which may not happen automatically while recompiling python files using touch wsgi.py approach. I don't have experience with this particular app, but for example with celery, which is a lot more sophisticated app for scheduling tasks, you would also have to restart the worker in order to reflect the changes in code, since worker actually stores a pickled version of the code.

Now after checking out the django-background-task app (which seems like the one you are using), in theory you should't have to do anything special, but just to make sure you can clear out any scheduled tasks and reschedule them again.

1

I had a similar problem and it was gunicorn cache wasn't updating.

First try

sudo systemctl restart gunicorn

if that doesn't solve it:

sudo systemctl start gunicorn
sudo systemctl enable gunicorn
sudo systemctl status gunicorn (Check for faults)
sudo systemctl daemon-reload
sudo systemctl restart gunicorn

That then should update the server

JohnnyQ
  • 484
  • 10
  • 23
0

It seems your result is not as you think it is, I just used the same format as you described and you see it works. You should check the function that it is returning proper data or not.

>>> a = (('label', {'k':'3'}),)
>>> print (a[0])
('label', {'k': '3'})

>>> a[0][1].update({'k':'6'})
>>> print (a[0])
('label', {'k': '6'})
>>> 

FYI, As you see Here, Tuples are immutable sequence types and therefore they do not support updating and that is why they do not need an update function to be defined.

If you want to update the result[0] which itself is a tuple, (as clearly understood by the error message shown ), you have to create a new tuple with the entities that are updated.

brainless coder
  • 6,310
  • 1
  • 20
  • 36