Change IPython working directory
Inserting image into IPython notebook markdown
Hi, I've read the two above links, and the second link seems most relevant. what the person describes - simply calling the subdirectory - doesn't work for me. For instance, I have an image 'gephi.png' in '/Graphs/gephi.png'
But when I write the following
from IPython.display import Image
path = "/Graphs/gephi.png"
i = Image(path)
i
no image pops up - Yup. No error. Just nothing pops up besides an empty square box image.
Clarification:
When I move the image to the regular director, the image pops up fine.
My only code change is path = "gephi.png"
IPython's Image display object takes three kinds of arguments
The first is raw image data (e.g. the results of open(filename).read():
with open("Graphs/graph.png") as f:
data = f.read()
Image(data=data)
The second model is to load an image from a filename. This is functionally the same as above, but IPython does the reading from the file:
Image(filename="Graphs/graph.png")
The third form is passing URLs. External URLs can be used, but relative URIs will serve files relative to the notebook's own directory:
Image(url="Graphs/graph.png")
Where this can get confusing is if you don't tell IPython which one of these you are specifying, and you just pass the one argument positionally:
Image("Graphs/graph.png")
IPython tries to guess what you mean in this case:
if it looks like a path and points to an existing file, use it as a filename
if it looks like a URL, use it as a URL
otherwise, fallback on embedding the string as raw png data
That #3 is the source of the most confusion. If you pass it a filename that doesn't exist,
you will get a broken image:
Image("/Graphs/graph.png")
Note that URLs to local files must be relative. Absolute URLs will generally be wrong:
Image(url="/Graphs/graph.png")
An example notebook illustrating these things.
Related
I am a beginner in Python and would like to execute a code which saves an image into particular directory.
The thing is, I would like to save image with a serial number so that I can have many images(each execution gives one image) in the directory.
plt.savefig('Images/Imageplot.png') ## Image saved to particular folder
About the serial number, you can use the uuid library to generate a random and unique id for an image. See more here: https://www.geeksforgeeks.org/generating-random-ids-using-uuid-python/
To save images, it is a bit more complicated. It requires you to import the os library.
Here is an example:
import os
UPLOADED_FILE_DIR_PATH = os.path.join(os.path.dirname(__file__), "static", "uploaded-images")
my_file_path = os.path.join(UPLOADED_FILE_DIR_PATH, my_filename)
image_file.save(my_file_path)
This is a block of code I used previously for my website, so it may not apply for you, depending on your situation. I personnaly like that method, but if you are unsatisfied, take a look at this for more options: https://towardsdatascience.com/loading-and-saving-images-in-python-ba5a1f5058fb
I have created a definition that loads every image from a called folder. I am now trying to create a code that will either 1) load a specific image when indexed, and/or 2) load an image at random. I have attached two screenshots of my code and the error I am receiving.
https://i.stack.imgur.com/nQKrV.png
https://i.stack.imgur.com/toXkI.png
It looks like you need to concatenate the directory path with the file name:
with open(os.path.join(rat110_GF_path, random_filename)) as file
lines = file.readlines()
I am running an analysis script in python that gives me some variables and an image that I save as a png file. I then use jinja2 to fill them into an html template and I use weasyprint to render the html into a PDF file that I save.
There are a number of questions on here that deal with this issue, but none of the suggested solutions have fixed my problem. I need to feed it the absolute path to the image, since the output data gets saved on a totally different part of my local disk than the code that generates it. Many of the offered solutions suggest to use something like request.base_url(), but that seems something to come from flask (I guess?) or something that is actually building an app as opposed to simply building a PDF file.
The function that generates the PDF file from the variables looks like this:
def create_pdf_report(varlist, outfile):
# Create Jinja environment and get template
from jinja2 import Environment, FileSystemLoader
env = Environment(loader=FileSystemLoader('<absolute-path-to-dir-with-template>'))
template = env.get_template('report_template.html')
# Render HTML with input variables
html_out = template.render(varlist)
# Generate PDF
from weasyprint import HTML
HTML(string=html_out).write_pdf(outfile)
The template is this:
<img src="{{ systematics_figure }}" alt="systematics" width="900" height="650">
And the varlist dictionary I pass in looks like this:
fig3_fname = '<absolute-path-to-image>'
varlist = {'systematics_figure': fig3_fname}
While plain variables that I give it render fine, the image is not displayed; I get its alt text instead. The process finishes fine but I can't get the png image to be displayed. When I stick in the absolute image path into the html file directly and open it in my browser, it appears fine.
What can I do to make this work?
I am on a macOS Sierra 10.12.6 and working in python 3.7.3.
Turns out the solution was to add base_url='.' in weasyprint.HTML():
HTML(string=html_out, base_url='.').write_pdf(outfile)
and to use png files instead of pdf figures.
I have this file "image.jp
and this .mp3 file:
"Green Day - When I Come Around [Official Music Video].mp3"
in the directory "test"
I have already successfully set tags as Author, Title, Album and etc using eyeD3 library.
and then I try to set the Cover Art.
I've tried two possibilities, but none of them worked:
First one: Mutagen:
from mutagen.mp3 import MP3
from mutagen.id3 import ID3, APIC, error
complete_file_path = "test\\"+"Green Day - When I Come Around [Official Music Video].mp3"
path_to_thumb_wf = "test\\"+"image.jpg"
audio = MP3(complete_file_path, ID3=ID3)
# add ID3 tag if it doesn't exist
try:
audio.add_tags()
except error:
pass
print(path_to_thumb_wf)
audio.tags.add(
APIC(
encoding=3, # 3 is for utf-8
mime='image/jpg', # image/jpeg or image/png
type=3, # 3 is for the cover image
desc=u'Cover',
data=open(path_to_thumb_wf, 'rb').read()
)
)
audio.save(v2_version=3)
And the solution using eyeD3
audiofile = eyed3.load(complete_file_path)
# read image into memory
imagedata = open(path_to_thumb_wf,"rb").read()
# append image to tags
audiofile.tag.images.set(3,imagedata,"image/jpeg", u"you can put a description here")
audiofile.tag.save()
I'm using python 3.5.2 on Windows 10. And i don't know if it could influence the result but i'll say anyway, the song has already a cover art that I'd like to change.
As explained in the ID3v2.3 section on APIC:
There may be several pictures attached to one file, each in their individual "APIC" frame, but only one with the same content descriptor. There may only be one picture with the picture type declared as picture type $01 and $02 respectively.
In v2.3, IIRC, "content descriptor" isn't actually documented anywhere, so different clients may do slightly different things here, but most tools will treat it either as the picture type plus description string, or as the entire header (text encoding, MIME type, picture type, and encoded description) as a binary blob. (And some tools just ignore it and allow you to store pictures with completely identical frame headers, but I don't think that's relevant with Mutagen.)
At any rate, this means you're probably just adding another Cover (front) picture, named 'Cover', rather than replacing any existing one.
You haven't explained how you're looking at the file. But I'm guessing you're trying to open it in Windows Media Player or iTunes or some other player, or view it in Windows Explorer (which I think just asks WMP to read the tag), or something like that?
Almost all such tools, when faced with multiple images, just show you the first one. (Some of them don't even distinguish on picture type, and show you the first image of any type, even if it's a 32x32 file icon…)
Some do have a way to view the other pictures, however. For example, in iTunes, if you Get Info or Properties on the track, then go to the Cover Art or similar tab (sorry for the vagueness, but the names have changed across versions), you can see all of the pictures in the tag.
At any rate, if you want to replace the APIC with a different one, you either need to exactly match the descriptor (and, again, that can mean different things to different libraries…), or, more simply, just delete the old one as well as adding the new one.
One more thing to watch out for: both iTunes and WMP cache cover art, and assume that it's never going to change once the file has been imported. And WMP also has various things that can override the image in the file, such as a properly-UUID'd folder cover art image in the same directory.
I am creating image that I would like to embed in the e-mail. I cannot figure out how to create image as binary and pass into MIMEImage. Below is the code I have and I have error when I try to read image object - the error is "AttributeError: 'NoneType' object has no attribute 'read'".
image=Image.new("RGBA",(300,400),(255,255,255))
image_base=ImageDraw.Draw(image)
emailed_password_pic=image_base.text((150,200),emailed_password,(0,0,0))
imgObj=emailed_password_pic.read()
msg=MIMEMultipart()
html="""<p>Please finish registration <br/><img src="cid:image.jpg"></p>"""
img_file='image.jpg'
msgText = MIMEText(html,'html')
msgImg=MIMEImage(imgObj)
msgImg.add_header('Content-ID',img_file)
msg.attach(msgImg)
msg.attach(msgText)
If you look at line 4 - I am trying to read image so that I can pass it into MIMEImage. Apparently, image needs to be read as binary. However, I don't know how to convert it to binary so that .read() can process it.
FOLLOW-UP
I edited code per suggestions from jsbueno - thank you very much!!!:
emailed_password=os.urandom(16)
image=Image.new("RGBA",(300,400),(255,255,255))
image_base=ImageDraw.Draw(image)
emailed_password_pic=image_base.text((150,200),emailed_password,(0,0,0))
stream_bytes=BytesIO()
image.save(stream_bytes,format='png')
stream_bytes.seek(0)
#in_memory_file=stream_bytes.getvalue()
#imgObj=in_memory_file.read()
imgObj=stream_bytes.read()
msg=MIMEMultipart()
sender='xxx#abc.com'
receiver='jjjj#gmail.com'
subject_header='Please use code provided in this e-mail to confirm your subscription.'
msg["To"]=receiver
msg["From"]=sender
msg["Subject"]=subject_header
html="""<p>Please finish registration by loging into your account and typing in code from this e-mail.<br/><img src="cid:image.png"></p>"""
img_file='image.png'
msgText=MIMEText(html,'html')
msgImg=MIMEImage(imgObj) #Is mistake here?
msgImg.add_header('Content-ID',img_file)
msg.attach(msgImg)
msg.attach(msgText)
smtpObj=smtplib.SMTP('smtp.mandrillapp.com', 587)
smtpObj.login(userName,userPassword)
smtpObj.sendmail(sender,receiver,msg.as_string())
I am not getting errors now but e-mail does not have image in it. I am confused about the way image gets attached and related to in html/email part. Any help is appreciated!
UPDATE:
This code actually works - I just had minor typo in the code on my PC.
There are a couple of conceptual errors there, both in using PIL and on what format an image should be in order to be incorporated into an e-mail.
In PIL: the ImageDraw class operates inplace, not like the Image class calls, which usually return a new image after each operation. In your code, it means that the call to image_base.text is actually changing the pixel data of the object that lies in your image variable. This call actually returns None and the code above should raise an error like "AttributeError: None object does not have attribute 'read'" on the following line.
Past that (that is, you should fetch the data from your image variable to attach it to the e-mail) comes the second issue: PIL, for obvious reasons, have images in an uncompressed, raw pixel data format in memory. When attaching images in e-mails we usually want images neatly packaged inside a file - PNG or JPG formats are usually better depending on the intent - let's just stay with .PNG. So, you have to create the file data using PIL, and them attach the file data (i.e. the data comprising a PNG file, including headers, metadata, and the actual pixel data in a compressed form). Otherwise you'd be putting in your e-mail a bunch of (uncompressed) pixel data that the receiving party would have no way to assemble back into an image (even if he would treat the data as pixels, raw pixel data does not contain the image shape so-)
You have two options: either generate the file-bytes in memory, or write them to an actual file in disk, and re-read that file for attaching. The second form is easier to follow. The first is both more efficient and "the right thing to do" - so let's keep it:
from io import BytesIO
# In Python 2.x:
# from StringIO import StringIO.StringIO as BytesIO
image=Image.new("RGBA",(300,400),(255,255,255))
image_base=ImageDraw.Draw(image)
# this actually modifies "image"
emailed_password_pic=image_base.text((150,200),emailed_password,(0,0,0))
stream = BytesIO()
image.save(stream, format="png")
stream.seek(0)
imgObj=stream.read()
...
(NB: I have not checked the part dealing with mail and mime proper in your code - if you are using it correctly, it should work now)