Attribute Error for Usage of Python Email Import - python

def ExtractBody(self, msg):
content = ""
if msg.is_multipart():
for payload in msg.get_payload():
content += str(payload.get_payload())
else:
content += str(msg.get_payload())
return content
Hello everyone, with the code above, I was trying to extract the body of a .eml file from a class, but when I used the code above, it gives me the error as shown below.
Why is this so, and how can I fix it?
For extra information, I am getting this email from a web server that makes use of flask.
<class 'AttributeError'>
'bytes' object has no attribute 'read'

EDIT: I have a temporary fix to the problem
I am not sure why, but when I shifted the method from the class to the .py file itself, the code now works.

Related

"dict" being interpreted as a "list" and I can't tell why

I have a strange problem and I can't seem to find a solution. I'm creating a Python app that sends a get request to an endpoint, fetches some data in JSON format and processes it to insert it into a database later. I have to classes, one is like APIClient, and the other is just a namespace to hold some methods to transform the data, let's call it APITransform.
There is a problematic method in APITransform, so here's the code.
#api.py module"
class APITransform:
...
#staticmethod
def flatten(data:dict, method:str):
if method == "some flattening method from a config file":
return list(data.values())
....
class APIClient:
....
def get_data():
....
response = requests.get(URL, headers, params)
json_resp = response.json()
json_resp = APITransform.flatten(
json_resp, "some flattening method from a config file")
#main.py module
from api import APIClient
api_client = APIClient()
api_client.get_data()
The error traces to APITransform.flatten() with the message:
return list(data.values())
AttributeError: 'list' object has no attribute 'values'
EDIT: The strange thing is that If I print the type of json_resp object before passing it to APITransform.flatten() in get_data(), I get two outputs in two lines: <class dict> and <class list>. It's like get_data() is being called twice, but I searched it in the entire project, I can only find it in two places, the definition in APIClient and call in main.py. I'm out of debugging ideas.
Anyone with an idea? Thanks
the code can raise such an error if the result of the json which is returned from a server, is a list, for example, if the response (from the server) is something like "[1,2,3]" or any other json list, the json_resp variable would be a list, that of course has no values() function. make sure the server returns the data in proper format or use an if statement to check before passing to the flatten function.

Python - Web Scraping exercise - Attribute Error

I am learning how to scrape web information. Below is a snippet of the actual code solution + output from datacamp.
On datacamp, this works perfectly fine, but when I try to run it on Spyder (my own macbook), it doesn't work...
This is because on datacamp, the URL has already been pre-loaded into a variable named 'response'.. however on Spyder, the URL needs to be defined again.
So, I first defined the response variable as response = requests.get('https://www.datacamp.com/courses/all') so that the code will point to datacamp's website..
My code looks like:
from scrapy.selector import Selector
import requests
response = requests.get('https://www.datacamp.com/courses/all')
this_url = response.url
this_title = response.xpath('/html/head/title/text()').extract_first()
print_url_title( this_url, this_title )
When I run this on Spyder, I got an error message
Traceback (most recent call last):
File "<ipython-input-30-6a8340fd3a71>", line 11, in <module>
this_title = response.xpath('/html/head/title/text()').extract_first()
AttributeError: 'Response' object has no attribute 'xpath'
Could someone please guide me? I would really like to know how to get this code working on Spyder.. thank you very much.
The value returned by requests.get('https://www.datacamp.com/courses/all') is a Response object, and this object has no attribute xpath, hence the error: AttributeError: 'Response' object has no attribute 'xpath'
I assume response from your tutorial source, probably has been assigned to another object (most likely the object returned by etree.HTML) and not the value returned by requests.get(url).
You can however do this:
from lxml import etree #import etree
response = requests.get('https://www.datacamp.com/courses/all') #get the Response object
tree = etree.HTML(response.text) #pass the page's source using the Response object
result = tree.xpath('/html/head/title/text()') #extract the value
print(response.url) #url
print(result) #findings

AttributeError: 'file' object has no attribute '_committed'

I have a DjangoFileField in my model. I am trying to convert the type of the audio from that FielField to mp3 and then again trying to save it. But after converting the type and exporting it using pydub it is returning the following error
AttributeError: 'file' object has no attribute '_committed'
My code is like this
def get_from_function(AudioSegment, format):
form = "from_{0}".format(format)
print form
if hasattr(AudioSegment, form):
return getattr(AudioSegment, form)
return None
audio = request.FILES.get('audio', None)
if audio:
name_list = audio.name.rsplit(".")
voice_format =name_list[1]
from_format = get_from_function(AudioSegment, voice_format)
if from_format and callable(from_format):
sound = from_format(audio)
audio = sound.export("media/{0}".format(name_list[0]), mp3")
when i print the audio it prints
<open file 'media/barsandtone', mode 'wb+' at 0x7f771e5e2f60>
and when i print the type of file it prints
<type 'file'>
but when i assign the audio field to django model like
Mymodel.objects.create(audio=audio)
it gives error
AttributeError at /create/
'file' object has no attribute '_committed'
What is the correct way to save the exported file into django model
django needs a ContentFile usually to do this passing it a stream of data, and it doesn't work the way you usually pass arguments to a model. The proper way to do this is the following
from django.core.files.base import ContentFile
[...]
mymodel = Mymodel()
mymodel.audio.save(audio.name, ContentFile(audio.read()))
don't forget to pass the stream to ContentFile. Django won't raise any errors if you pass it ContentFile(audio) but in that case you won't save the file content..
I got same error that is solved now i would suggest you to open that file in read mode then save it. here is my code :
from django.core.files import File as DjangoFile
file_obj1 = DjangoFile(open(file_name, mode='rb'), name=file_name)
File.objects.create(title=file_name, file=file_obj1, content_object=task_obj, author=task_obj.client)
In my case I was creating a django form with some FileFields for which I wanted to show the currently existing file from a model's instance. I'm leaving this answer here in case anyone else end up here for similar reasons, even though I know that this answer doesn't apply to the OP's situation.
Normally you would bound the form and the model but in this case it's not possible for reasons a bit long to explain, so I wanted to query the model to obtain the File field and make it be the initial data.
It reached a point where I managed to make it work until the view can render the field and the currently existing field (as it's normally rendered by the ClearableFileInput widget).
That point was reached by filling self.fields["field_name"].initial with either:
Using a DummyFile class:
class DummyFile:
def __init__(self, url, name):
self.url = url
self.name = name
def __str__(self):
return self.name
Filling it with the existing instance, like
self.fields[field_name].initial = doc.file.instance
self.fields[field_name].initial.url = doc.file.url
But then in both cases the AttributeError: 'file' object has no attribute '_committed' was raised when uploading a file, although it was correctly uploaded and saved.
Solution
Turned out that it behaves different when you assign the initial data for a field by using self.fields[field_name].initial than using self.initial[field_name], and doing it like this worked like a charm:
doc = Document.objects.filter(
filters_to_locate_the_model_instance=this_and_that,
).first()
if doc:
self.initial[field_name] = doc.file
The HTML is rendered with the link to the existing file, it loads fine if there is not an existing file, and uploads and saves a file without any error.

Why do I get "'str' object has no attribute 'read'" when trying to use `json.load` on a string? [duplicate]

This question already has answers here:
How can I parse (read) and use JSON?
(5 answers)
Closed 29 days ago.
In Python I'm getting an error:
Exception: (<type 'exceptions.AttributeError'>,
AttributeError("'str' object has no attribute 'read'",), <traceback object at 0x1543ab8>)
Given python code:
def getEntries (self, sub):
url = 'http://www.reddit.com/'
if (sub != ''):
url += 'r/' + sub
request = urllib2.Request (url +
'.json', None, {'User-Agent' : 'Reddit desktop client by /user/RobinJ1995/'})
response = urllib2.urlopen (request)
jsonStr = response.read()
return json.load(jsonStr)['data']['children']
What does this error mean and what did I do to cause it?
The problem is that for json.load you should pass a file like object with a read function defined. So either you use json.load(response) or json.loads(response.read()).
Ok, this is an old thread but.
I had a same issue, my problem was I used json.load instead of json.loads
This way, json has no problem with loading any kind of dictionary.
Official documentation
json.load - Deserialize fp (a .read()-supporting text file or binary file containing a JSON document) to a Python object using this conversion table.
json.loads - Deserialize s (a str, bytes or bytearray instance containing a JSON document) to a Python object using this conversion table.
You need to open the file first. This doesn't work:
json_file = json.load('test.json')
But this works:
f = open('test.json')
json_file = json.load(f)
If you get a python error like this:
AttributeError: 'str' object has no attribute 'some_method'
You probably poisoned your object accidentally by overwriting your object with a string.
How to reproduce this error in python with a few lines of code:
#!/usr/bin/env python
import json
def foobar(json):
msg = json.loads(json)
foobar('{"batman": "yes"}')
Run it, which prints:
AttributeError: 'str' object has no attribute 'loads'
But change the name of the variablename, and it works fine:
#!/usr/bin/env python
import json
def foobar(jsonstring):
msg = json.loads(jsonstring)
foobar('{"batman": "yes"}')
This error is caused when you tried to run a method within a string. String has a few methods, but not the one you are invoking. So stop trying to invoke a method which String does not define and start looking for where you poisoned your object.
AttributeError("'str' object has no attribute 'read'",)
This means exactly what it says: something tried to find a .read attribute on the object that you gave it, and you gave it an object of type str (i.e., you gave it a string).
The error occurred here:
json.load(jsonStr)['data']['children']
Well, you aren't looking for read anywhere, so it must happen in the json.load function that you called (as indicated by the full traceback). That is because json.load is trying to .read the thing that you gave it, but you gave it jsonStr, which currently names a string (which you created by calling .read on the response).
Solution: don't call .read yourself; the function will do this, and is expecting you to give it the response directly so that it can do so.
You could also have figured this out by reading the built-in Python documentation for the function (try help(json.load), or for the entire module (try help(json)), or by checking the documentation for those functions on http://docs.python.org .
Instead of json.load() use json.loads() and it would work:
ex:
import json
from json import dumps
strinjJson = '{"event_type": "affected_element_added"}'
data = json.loads(strinjJson)
print(data)
So, don't use json.load(data.read()) use json.loads(data.read()):
def findMailOfDev(fileName):
file=open(fileName,'r')
data=file.read();
data=json.loads(data)
return data['mail']
use json.loads() function , put the s after that ... just a mistake btw i just realized after i searched error
def getEntries (self, sub):
url = 'http://www.reddit.com/'
if (sub != ''):
url += 'r/' + sub
request = urllib2.Request (url +
'.json', None, {'User-Agent' : 'Reddit desktop client by /user/RobinJ1995/'})
response = urllib2.urlopen (request)
jsonStr = response.read()
return json.loads(jsonStr)['data']['children']
try this
Open the file as a text file first
json_data = open("data.json", "r")
Now load it to dict
dict_data = json.load(json_data)
If you need to convert string to json. Then use loads() method instead of load(). load() function uses to load data from a file so used loads() to convert string to json object.
j_obj = json.loads('["label" : "data"]')

AppEngine -> "AttributeError: 'unicode' object has no attribute 'has_key'" when using blobstore

There have been a number of other questions on AttributeErrors here, but I've read through them and am still not sure what's causing the type mismatch in my specific case.
Thanks in advance for any thoughts on this.
My model:
class Object(db.Model):
notes = db.StringProperty(multiline=False)
other_item = db.ReferenceProperty(Other)
time = db.DateTimeProperty(auto_now_add=True)
new_files = blobstore.BlobReferenceProperty(required=True)
email = db.EmailProperty()
is_purple = db.BooleanProperty()
My BlobstoreUploadHandler:
class FormUploadHandler(blobstore_handlers.BlobstoreUploadHandler):
def post(self):
try:
note = self.request.get('notes')
email_addr = self.request.get('email')
o = self.request.get('other')
upload_file = self.get_uploads()[0]
# Save the object record
new_object = Object(notes=note,
other=o,
email=email_addr,
is_purple=False,
new_files=upload_file.key())
db.put(new_object)
# Redirect to let user know everything's peachy.
self.redirect('/upload_success.html')
except:
self.redirect('/upload_failure.html')
And every time I submit the form that uploads the file, it throws the following exception:
ERROR 2010-10-30 21:31:01,045 __init__.py:391] 'unicode' object has no attribute 'has_key'
Traceback (most recent call last):
File "/home/user/Public/dir/google_appengine/google/appengine/ext/webapp/__init__.py", line 513, in __call__
handler.post(*groups)
File "/home/user/Public/dir/myapp/myapp.py", line 187, in post
new_files=upload_file.key())
File "/home/user/Public/dir/google_appengine/google/appengine/ext/db/__init__.py", line 813, in __init__
prop.__set__(self, value)
File "/home/user/Public/dir/google_appengine/google/appengine/ext/db/__init__.py", line 3216, in __set__
value = self.validate(value)
File "/home/user/Public/dir/google_appengine/google/appengine/ext/db/__init__.py", line 3246, in validate
if value is not None and not value.has_key():
AttributeError: 'unicode' object has no attribute 'has_key'
What perplexes me most is that this code is nearly straight out of the documentation, and jives with other examples of blob upload handler's I've found online in tutorials as well.
I've run --clear-datastore to ensure that any changes I've made to the DB schema aren't causing problems, and have tried casting upload_file as all sorts of things to see if it would appease Python - any ideas on what I've screwed up?
Edit: I've found a workaround, but it's suboptimal.
Altering the UploadHandler to this instead resolves the issue:
...
# Save the object record
new_object = Object()
new_object.notes = note
new_object.other = o
new_object.email = email.addr
new_object.is_purple = False
new_object.new_files = upload_file.key()
db.put(new_object)
...
I made this switch after noticing that commenting out the files line threw the same issues for the other line, and so on. This isn't an optimal solution, though, as I can't enforce validation this way (in the model, if I set anything as required, I can't declare an empty entity like above without throwing an exception).
Any thoughts on why I can't declare the entity and populate it at the same time?
You're passing in o as the value of other_item (in your sample code, you call it other, but I presume that's a typo). o is a string fetched from the request, though, and the model definition specifies that it's a ReferenceProperty, so it should either be an instance of the Other class, or a db.Key object.
If o is supposed to be a stringified key, pass in db.Key(o) instead, to deserialize it.
Object is a really terrible name for a datastore class (or any class, really), by the way - the Python base object is called object, and that's only one capitalized letter away - very easy to mistake.
has_key error is due to the ReferenceProperty other_items. You are most likely passing in '' for other_items when appengine's api expects a dict. In order to get around this, you need to convert other_items to hash.
[caveat lector: I know zilch about "google_app_engine"]
The message indicates that it is expecting a dict (the only known object that has a has_key attribute) or a work-alike object, not the unicode object that you supplied. Perhaps you should be passing upload_file, not upload_file.key() ...

Categories