'Thread' object has no attribute '_children' - django + scikit-learn - python

I'm having problems with a django application that uses a random forest classifier (http://scikit-learn.org/stable/modules/generated/sklearn.ensemble.RandomForestClassifier.html) to classify items. The error that I'm receiving says:
AttributeError at /items/
'Thread' object has no attribute '_children'
Request Method: POST
Request URL: http://localhost:8000/items/
Django Version: 1.7.6
Exception Type: AttributeError
Exception Value:
'Thread' object has no attribute '_children'
Exception Location: /usr/lib/python2.7/multiprocessing/dummy/__init__.py in start, line 73
Python Executable: /home/cristian/env/bin/python
Python Version: 2.7.3
Python Path:
['/home/cristian/filters',
'/home/cristian/env/lib/python2.7',
'/home/cristian/env/lib/python2.7/plat-linux2',
'/home/cristian/env/lib/python2.7/lib-tk',
'/home/cristian/env/lib/python2.7/lib-old',
'/home/cristian/env/lib/python2.7/lib-dynload',
'/usr/lib/python2.7',
'/usr/lib/python2.7/plat-linux2',
'/usr/lib/python2.7/lib-tk',
'/home/cristian/env/local/lib/python2.7/site-packages']
Server time: Fri, 24 Apr 2015 16:08:20 +0000
The problem is that I'm not using threads at all. This is the code:
def item_to_dict(item):
item_dict = {}
for key in item:
value = item[key]
# fix encoding
if isinstance(value, unicode):
value = value.encode('utf-8')
item_dict[key] = [value]
return item_dict
def load_classifier(filter_name):
clf = joblib.load(os.path.join(CLASSIFIERS_PATH, filter_name, 'random_forest.100k.' + filter_name.lower() + '.pkl'))
return clf
#api_view(['POST'])
def classify_item(request):
"""
Classify item
"""
if request.method == 'POST':
serializer = ItemSerializer(data=request.data['item'])
if serializer.is_valid():
# get item and filter_name
item = serializer.data
filter_name = request.data['filter']
item_dict = item_to_dict(item)
clf = load_classifier(filter_name)
# score item
y_pred = clf.predict_proba(pd.DataFrame(item_dict))
item_score = y_pred[0][1]
# create and save classification
classification = Classification(classifier_name=filter_name,score=item_score,item_id=item['_id'])
classification_serializer = ClassificationSerializer(classification)
return Response(classification_serializer.data, status=status.HTTP_201_CREATED)
else:
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
I'm able to print out the "clf" and "item_dict" variables and everything seems ok. The error raises when I call the method "predict_proba" of the classifier.
One important thing to add is that I don't recieve the error when I run the server and send the post method for the first time.
Here's the full traceback:
File "/home/cristian/env/local/lib/python2.7/site-packages/django/core/handlers/base.py" in get_response
line 111. response = wrapped_callback(request, *callback_args, **callback_kwargs)
File "/home/cristian/env/local/lib/python2.7/site-packages/django/views/decorators/csrf.py" in wrapped_view
line 57. return view_func(*args, **kwargs)
File "/home/cristian/env/local/lib/python2.7/site-packages/django/views/generic/base.py" in view
line 69. return self.dispatch(request, *args, **kwargs)
File "/home/cristian/env/local/lib/python2.7/site-packages/rest_framework/views.py" in dispatch
line 452. response = self.handle_exception(exc)
File "/home/cristian/env/local/lib/python2.7/site-packages/rest_framework/views.py" in dispatch
line 449. response = handler(request, *args, **kwargs)
File "/home/cristian/env/local/lib/python2.7/site-packages/rest_framework/decorators.py" in handler
line 50. return func(*args, **kwargs)
File "/home/cristian/filters/classifiers/views.py" in classify_item
line 70. y_pred = clf.predict_proba(pd.DataFrame(item_dict))
File "/home/cristian/env/local/lib/python2.7/site-packages/sklearn/pipeline.py" in predict_proba
line 159. return self.steps[-1][-1].predict_proba(Xt)
File "/home/cristian/env/local/lib/python2.7/site-packages/sklearn/ensemble/forest.py" in predict_proba
line 468. for i in range(n_jobs))
File "/home/cristian/env/local/lib/python2.7/site-packages/sklearn/externals/joblib/parallel.py" in __call__
line 568. self._pool = ThreadPool(n_jobs)
File "/usr/lib/python2.7/multiprocessing/pool.py" in __init__
line 685. Pool.__init__(self, processes, initializer, initargs)
File "/usr/lib/python2.7/multiprocessing/pool.py" in __init__
line 136. self._repopulate_pool()
File "/usr/lib/python2.7/multiprocessing/pool.py" in _repopulate_pool
line 199. w.start()
File "/usr/lib/python2.7/multiprocessing/dummy/__init__.py" in start
line 73. self._parent._children[self] = None
Exception Type: AttributeError at /items/
Exception Value: 'Thread' object has no attribute '_children'

As a workaround, you can disable the threading at prediction time with:
clf = load_classifier(filter_name)
clf.set_params(n_jobs=1)
y_pred = clf.predict_proba(pd.DataFrame(item_dict))
Also note, calling load_classifier at each request might be expensive it actually loads the model from the disk.
You can pass mmap_mode='r' to joblib.load to memory map the data from the disk. It will make it possible to load the model only once even if you have concurrent requests accessing the same model parameters concurrently (both with different threads and different Python processes if you use something like gunicorn).

It looks like that problem was fixed from Python 2.7.5. It was basically a bug in multiprocessing.

Related

Access cleaned data from django admin for pdf processing

As a newbie, I am currently trying to add a print button to every existing django admin view of a project.
The goal is to make it not depend on a single model I could resolve manually for printing but every existing model which contains foreign keys to other models an so on.
For simplicity I thought it would be the best to just get the cleaned_data of the form and process it for the pdf.
I alread added the print button, the path url and so on and it will create a pdf file for me.
What I am not able to do is to access the forms cleaned_data from my BaseAdmins (extends the ModelAdmin) class like this:
form = BaseForm(request.POST)
if form.is_valid():
data = form.cleaned_data
It will just give me random kinds of errors, like object has no attribute 'is_bound'
So I think that I am generally wrong with the context where I am trying to get the cleaned_data from the form. Every tutorial I found is just showing how to get the data but not fully resolved if it contains foreign keys and not in which context.
Could you please clear up for me where it would make sense to pass any kind of form data maybe as session data or post body to a print view where I can process it.
Thank you very much for reading, hope I was able to describe my problem, feel free to ask.
Edit
This is the BaseForm I changed variable names for internal reasons:
class BaseForm(ModelForm):
def clean_custom(self):
another_model = self.cleaned_data.get('AnotherModel')
custom_models = self.cleaned_data.get('CustomModel')
custom_models_allowed = CustomModel.objects.filter(AnotherModel=another_model)
custom_models_was_list = True
if not custom_models:
return
if not isinstance(custom_models, Iterable):
custom_models_was_list = False
custom_models = [custom_models]
for custom_model in custom_models:
if another_model and custom_model not in custom_models_allowed:
custom_models_allowed = [custom_model.titel for custom_model in custom_models_allowed]
custom_models_allowed = ', '.join(custom_models_allowed)
raise ValidationError(
f'{custom_model} is not part of {another_model}. For selection: {custom_models_allowed}'
)
if custom_models_was_list:
return custom_models
else:
return custom_models[0]
I'm trying to add cleaned_data in my BaseAdmin class where I have access to request and get the following trace:
AttributeError
AttributeError: type object 'CustomForm' has no attribute 'is_bound'
Traceback (most recent call last)
File ".../.env/lib/python3.9/site-packages/django/contrib/staticfiles/handlers.py", line 65, in __call__
return self.application(environ, start_response)
File ".../.env/lib/python3.9/site-packages/django/core/handlers/wsgi.py", line 141, in __call__
response = self.get_response(request)
File ".../.env/lib/python3.9/site-packages/django/core/handlers/base.py", line 75, in get_response
response = self._middleware_chain(request)
File ".../.env/lib/python3.9/site-packages/django/core/handlers/exception.py", line 36, in inner
response = response_for_exception(request, exc)
File ".../.env/lib/python3.9/site-packages/django/core/handlers/exception.py", line 90, in response_for_exception
response = handle_uncaught_exception(request, get_resolver(get_urlconf()), sys.exc_info())
File ".../.env/lib/python3.9/site-packages/django/core/handlers/exception.py", line 125, in handle_uncaught_exception
return debug.technical_500_response(request, *exc_info)
File ".../.env/lib/python3.9/site-packages/django_extensions/management/technical_response.py", line 40, in null_technical_500_response
raise exc_value.with_traceback(tb)
File ".../.env/lib/python3.9/site-packages/django/core/handlers/exception.py", line 34, in inner
response = get_response(request)
File ".../.env/lib/python3.9/site-packages/django/core/handlers/base.py", line 115, in _get_response
response = self.process_exception_by_middleware(e, request)
File ".../.env/lib/python3.9/site-packages/django/core/handlers/base.py", line 113, in _get_response
response = wrapped_callback(request, *callback_args, **callback_kwargs)
File ".../.env/lib/python3.9/site-packages/django/contrib/admin/options.py", line 606, in wrapper
return self.admin_site.admin_view(view)(*args, **kwargs)
File ".../.env/lib/python3.9/site-packages/django/utils/decorators.py", line 142, in _wrapped_view
response = view_func(request, *args, **kwargs)
File ".../.env/lib/python3.9/site-packages/django/views/decorators/cache.py", line 44, in _wrapped_view_func
response = view_func(request, *args, **kwargs)
File ".../.env/lib/python3.9/site-packages/django/contrib/admin/sites.py", line 223, in inner
return view(request, *args, **kwargs)
File ".../admin/base_admin.py", line 203, in change_view
if self.form.is_valid(self.form):
File ".../.env/lib/python3.9/site-packages/django/forms/forms.py", line 185, in is_valid
return self.is_bound and not self.errors
AttributeError: type object 'CustomForm' has no attribute 'is_bound'
This is not a standard question format, you are supposed to give us the code for the piece of code where the error occurs, (i.e. the base_admin.py file) but what you have provided is just 3 lines of it.
But so far I can see you are not checking whether the request is of the type of post or not. Pay attention to the if condition at the beginning of the method
def edit(request):
if request.method == 'POST':
# create a form instance and populate it with data from the request:
form = PurposeForm(request.POST)
# check whether it's valid:
if form.is_valid():
for key, value in form.cleaned_data.items():
# etc

DRF - 'str' object has no attribute 'pk'

I've got a front-end that sends JSON to the back-end to switch the input of a digital audio stream, with an optional time component to schedule the switch for the future. Here are the components of making this work:
from views.py:
class SwitchStreamView(views.APIView):
"""
A custom endpoint for switching inputs of radio streams
"""
queryset = RadioStream.objects.all()
def post(self, request, format=None):
serializer = serializers.RadioSwitchSerializer(data=request.data, many=True)
serializer.is_valid()
for stream in serializer.data:
if stream.schedule_time is None:
tasks.switch_stream(stream.mnemonic, stream.current_input)
else:
tasks.schedule_switch(stream.mnemonic, stream.current_input, stream.schedule_time)
return HttpResponse('')
from serializers.py:
class RadioSwitchSerializer(serializers.ModelSerializer):
schedule_time = serializers.SerializerMethodField()
def get_schedule_time(self, obj):
return obj.get('schedule_time', None)
class Meta:
model = RadioStream
fields = ('mnemonic', 'current_input', 'schedule_time')
The issue I'm having is that however I try and send a test JSON snippet, I'm getting errors. With this setup, sending
[
{
"mnemonic": "TEST",
"current_input": "TEST"
}
]
results in the error 'str' object has no attribute 'pk', but if I change RadioSwitchSerializer(data=request.data, many=True) to many=False, and send
{
"mnemonic": "TEST",
"current_input": "TEST"
}
I get the response 'str' object has no attribute 'schedule_time' instead.
My plan was to use mnemonic to identify the stream, and current_input to identify which input to switch it to. My questions are; Why is this not working, and should I be using a non-Model serializer for this custom action instead of trying to fit the action into the existing fields of the model?
Edit: Here is the traceback
Internal Server Error: /api/switch/
Traceback (most recent call last):
File "...\lib\site-packages\django\core\handlers\exception.py", line 35, in inner
response = get_response(request)
File "...\lib\site-packages\django\core\handlers\base.py", line 128, in _get_response
response = self.process_exception_by_middleware(e, request)
File "...\lib\site-packages\django\core\handlers\base.py", line 126, in _get_response
response = wrapped_callback(request, *callback_args, **callback_kwargs)
File "...\lib\site-packages\django\views\decorators\csrf.py", line 54, in wrapped_view
return view_func(*args, **kwargs)
File "...\lib\site-packages\django\views\generic\base.py", line 69, in view
return self.dispatch(request, *args, **kwargs)
File "...\lib\site-packages\rest_framework\views.py", line 489, in dispatch
response = self.handle_exception(exc)
File "...\lib\site-packages\rest_framework\views.py", line 449, in handle_exception
self.raise_uncaught_exception(exc)
File "...\lib\site-packages\rest_framework\views.py", line 486, in dispatch
response = handler(request, *args, **kwargs)
File "...\radio_switching\views.py", line 45, in post
for stream in serializer.data:
File "...\lib\site-packages\rest_framework\serializers.py", line 738, in data
ret = super(ListSerializer, self).data
File "...\lib\site-packages\rest_framework\serializers.py", line 266, in data
self._data = self.get_initial()
File "...\lib\site-packages\rest_framework\serializers.py", line 573, in get_initial
return self.to_representation(self.initial_data)
File "...\lib\site-packages\rest_framework\serializers.py", line 656, in to_representation
self.child.to_representation(item) for item in iterable
File "...\lib\site-packages\rest_framework\serializers.py", line 656, in <listcomp>
self.child.to_representation(item) for item in iterable
File "...\lib\site-packages\rest_framework\serializers.py", line 500, in to_representation
ret[field.field_name] = field.to_representation(attribute)
File "...\lib\site-packages\rest_framework\relations.py", line 259, in to_representation
return value.pk
AttributeError: 'str' object has no attribute 'pk'
replace your views.py by this snippet,
class SwitchStreamView(views.APIView):
"""
A custom endpoint for switching inputs of radio streams
"""
queryset = RadioStream.objects.all()
def post(self, request, format=None):
serializer = serializers.RadioSwitchSerializer(data=request.data, many=True)
serializer.is_valid()
for stream in serializer.data:
if 'schedule_time' not in stream:
tasks.switch_stream(stream['mnemonic'], stream['current_input'])
else:
tasks.schedule_switch(stream['mnemonic'], stream['current_input'], stream['schedule_time'])
return HttpResponse('')
The reason for the error is, you are trying to access a python dict using dot operator. To access dictionary elements, you can use the familiar square brackets along with the key to obtaining it's value. Here is the official doc
EDIT
AttributeError: 'str' object has no attribute 'pk' this error because, somewhere you trying to access .pk from a str object
Reproducing the error
In [7]: my_str = 'this is just a string'
In [8]: my_str.pk
---------------------------------------------------------------------------
AttributeError Traceback (most recent call last)
<ipython-input-8-5bc39c990550> in <module>()
----> 1 my_str.pk
AttributeError: 'str' object has no attribute 'pk'
There were a few issues, but it turns out the root issue was that serlializer.data was for whatever reason returning a string and not an array of objects. I ended up replacing the ModelSerializer with a regular Serializer here:
class RadioSwitchSerializer(serializers.Serializer):
mnemonic = serializers.CharField(max_length=20)
new_input = serializers.CharField(max_length=20)
schedule_time = serializers.DateTimeField(allow_null=True)
As per Jerin's answer, I also fixed up the lines accessing the stream dictionary to use square brackets rather than the dot operator. These two things have fixed the issue.

SyntaxError uncaught while using py_compile

I have defined the following function inside a class in python, where I'm trying to compile python code from external source.
The python code comes in, is written to a file and then the file is sent to the below function.
When I'm trying to call the function as:
self._check_code_for_errors(source_file)
It does not execute the except block, where I'm catching the SyntaxError exception.
def _check_code_for_errors(self, source_file):
try:
file_ = open(source_file.name, 'r')
py_compile.compile(file_.name)
except SyntaxError:
return {'errors': 'You have a problem in your syntax'}
except (OSError, IOError):
return {'errors': 'Some error has occurred, please try again'}
Update:
class ValidatePythonCodeViewSet(generics.CreateAPIView):
parser_classes = (PlainTextParser, )
"""
The view set below accepts code from post request, executes it and then
returns the appropriate results (error or output)
"""
def _write_code_to_file(self, source):
# file is a reserved word in python 2.x, so using file_
with open('tempPythonCode.py', 'w') as file_:
file_.write(source)
return file_
def _check_code_for_errors(self, source_file):
try:
file_ = open(source_file.name, 'r')
py_compile.compile(file_.name, doraise=True)
except py_compile.PyCompileError:
return {'errors': 'You have a problem in your syntax'}
def post(self, request, *args, **kwargs):
source = request.data
if not source:
raise InformationMissingInRequestError()
else:
source_file = self._write_code_to_file(source)
response = self._check_code_for_errors(source_file)
if response.get('errors', None):
return Response(response, status=status.HTTP_400_BAD_REQUEST)
else:
#execute code here and return
pass
return Response(response, status=status.HTTP_200_OK)
The request that I'm making is:
TraceBack
File "tempPythonCode.py", line 1
import os\nprint 'hi
^
SyntaxError: unexpected character after line continuation character
Internal Server Error: /api/python/
Traceback (most recent call last):
File "/home/dhruuv/.virtualenvs/pythoneval/local/lib/python2.7/site-packages/django/core/handlers/base.py", line 149, in get_response
response = self.process_exception_by_middleware(e, request)
File "/home/dhruuv/.virtualenvs/pythoneval/local/lib/python2.7/site-packages/django/core/handlers/base.py", line 147, in get_response
response = wrapped_callback(request, *callback_args, **callback_kwargs)
File "/home/dhruuv/.virtualenvs/pythoneval/local/lib/python2.7/site-packages/django/views/decorators/csrf.py", line 58, in wrapped_view
return view_func(*args, **kwargs)
File "/home/dhruuv/.virtualenvs/pythoneval/local/lib/python2.7/site-packages/django/views/generic/base.py", line 68, in view
return self.dispatch(request, *args, **kwargs)
File "/home/dhruuv/.virtualenvs/pythoneval/local/lib/python2.7/site-packages/rest_framework/views.py", line 466, in dispatch
response = self.handle_exception(exc)
File "/home/dhruuv/.virtualenvs/pythoneval/local/lib/python2.7/site-packages/rest_framework/views.py", line 463, in dispatch
response = handler(request, *args, **kwargs)
File "/home/dhruuv/projects/PythonEval/api/views.py", line 44, in post
if response.get('errors', None):
AttributeError: 'NoneType' object has no attribute 'get'
[10/Feb/2016 09:45:44] "POST /api/python/ HTTP/1.1" 500 87401
Update 2
I tried it in ipdb, which worked just fine!
In [5]: try:
py_compile.compile('testing.py', doraise=True)
except py_compile.PyCompileError:
print 'dfsssssssssssss'
...:
dfsssssssssssss
Any help is appreciated.
SyntaxError is not a runtime error, and you cannot catch it in code. However, py_compile does not raise SyntaxError; as the documentation shows, it raises py_compile.PyCompileError.
Edit So there are a couple of things wrong with your code here. Firstly, again as the documentation shows, you need to pass doraise=True to compile in order to get it to raise an error.
And the other exception is happening because you're not returning anything from _check_code_for_errors if it succeeds. You probably should return an empty dict.

How to use AssertRaisesMessage() in Django tests

I followed the Django doc to write tests with assertRaisesMessage() but the problem is the exception itself is raised when executing test (so, the test is not executed).
Note that the exception called is an exception I voluntarily raise in a method of my model (not in the view).
class MyTestCase(TestCase):
def test_invertRewardState_view_fails_notmy_reward(self):
self.client.login(email='gislaine#toto.com', password='azerty')
resp = self.client.get(reverse(invertRewardState, args=(1,)))
self.assertRaisesMessage(
expected_exception=Exception,
expected_message=EXC_NOT_YOURS,
callable_obj=resp)
How Should I use AssertRaisesMessage() to let my test be executed without raising the Exception?
Thanks.
EDIT :
After trying falsetru 1st solution, the problem is still the same. As soon as my test enters in the resp = ... part, view is called, then related model method is called and raises the exception.
the full stack trace :
Traceback (most recent call last):
File "/Users/walt/Code/hellodjango/clientizr/tests.py", line 338, in test_invertRewardState_view_fails_notmy_reward
resp = self.client.get(reverse(invertRewardState, args=('1',)))
File "/Users/walt/Code/hellodjango/venv/lib/python2.7/site-packages/django/test/client.py", line 473, in get
response = super(Client, self).get(path, data=data, **extra)
File "/Users/walt/Code/hellodjango/venv/lib/python2.7/site-packages/django/test/client.py", line 280, in get
return self.request(**r)
File "/Users/walt/Code/hellodjango/venv/lib/python2.7/site-packages/django/test/client.py", line 444, in request
six.reraise(*exc_info)
File "/Users/walt/Code/hellodjango/venv/lib/python2.7/site-packages/django/core/handlers/base.py", line 114, in get_response
response = wrapped_callback(request, *callback_args, **callback_kwargs)
File "/Users/walt/Code/hellodjango/venv/lib/python2.7/site-packages/django/contrib/auth/decorators.py", line 22, in _wrapped_view
return view_func(request, *args, **kwargs)
File "/Users/walt/Code/hellodjango/clientizr/views.py", line 234, in invertRewardState
reward.invert_reward_state(request.user)
File "/Users/walt/Code/hellodjango/clientizr/models.py", line 606, in invert_reward_state
self.throw_error_if_not_owner_reward(cur_user)
File "/Users/walt/Code/hellodjango/clientizr/models.py", line 587, in throw_error_if_not_owner_reward
raise Exception(EXC_NOT_YOURS)
Exception: Cet objet n'est pas le v\xf4tre
You use assertRaisesMessage as a context manager around the code you expect to fail:
class MyTestCase(TestCase):
def test_invertRewardState_view_fails_notmy_reward(self):
self.client.login(email='gislaine#toto.com', password='azerty')
url = reverse(invertRewardState, args=(1,))
with self.assertRaisesMessage(Exception, EXC_NOT_YOURS):
self.client.get(url)
If you use self.client.get, you will not get an exception directly, but you can check status code.
def test_invertRewardState_view_fails_notmy_reward(self):
self.client.login(email='gislaine#toto.com', password='azerty')
resp = self.client.get(reverse(invertRewardState, args=('1',)))
self.assertEqual(resp.status_code, 500)
self.assertIn(EXC_NOT_YOURS in resp.content)
If you want to get an exception, call the view directly.
def test_invertRewardState_view_fails_notmy_reward(self):
request = HttpRequest()
request.user = User.objects.create(email='gislaine#toto.com') # login
self.assertRaisesMessage(Exception, EXC_NOT_YOURS, invertRewardState, '1')
You can use context manager form as Ned Batchelder suggested.

Django rss feedparser returns a feed with no "title"

I'm writing a basic RSS feed reader in Django. I have a form in which a user submits a rss feed, and I add it to his feeds list. But for some reason, I'm unable to extract basic information about the feed using feed parser.
when i run the following code:
def form_valid(self, form):
user = self.request.user
link = form.cleaned_data['link']
feed = feedparser.parse(link).feed
title = feed.title
try:
feed_obj = Feed.objects.get(link=link)
except ObjectDoesNotExist:
feed_obj = Feed(link=link, title=title)
feed_obj.save()
user.get_profile().feeds.add(feed_obj)
return super(DashboardView, self).form_valid(form)
Django throws me an "object has no attribute 'title'" exception on line 5:
title = feed.title
Full error details are:
Traceback:
File "/home/yaniv/nextfeed/venv/local/lib/python2.7/site-packages/django/core/handlers/base.py" in get_response
115. response = callback(request, *callback_args, **callback_kwargs)
File "/home/yaniv/nextfeed/venv/local/lib/python2.7/site-packages/django/contrib/auth/decorators.py" in _wrapped_view
25. return view_func(request, *args, **kwargs)
File "/home/yaniv/nextfeed/venv/local/lib/python2.7/site-packages/django/views/generic/base.py" in view
68. return self.dispatch(request, *args, **kwargs)
File "/home/yaniv/nextfeed/venv/local/lib/python2.7/site-packages/django/views/generic/base.py" in dispatch
86. return handler(request, *args, **kwargs)
File "/home/yaniv/nextfeed/venv/local/lib/python2.7/site-packages/django/views/generic/edit.py" in post
165. return self.form_valid(form)
File "/home/yaniv/nextfeed/profiles/views.py" in form_valid
48. title = feed.title
File "/home/yaniv/nextfeed/venv/local/lib/python2.7/site-packages/feedparser.py" in __getattr__
416. raise AttributeError, "object has no attribute '%s'" % key
Exception Type: AttributeError at /dashboard
Exception Value: object has no attribute 'title'
What am I doing wrong?
EDIT: I traced the program with pdb. Right before the problematic line, I got:
(Pdb) link
u'http://feedparser.org/docs/examples/rss20.xml'
(Pdb) feed
{'xhtml_script': {'type': u'text/javascript', 'language': u'javascript'}, 'summary': u''}
It's been a while since I used feedparser, but IIRC, the parser returns a dictionary, like so:
foo = feedparser.parse(link)
feed = foo['feed']
title = feed['title']
You seem to have gotten an object back from foo.feed, but that's not what you want.

Categories

Resources