Python file delete PermissionError: [WinError 32] - python

I am trying to delete a duplicated image by comparing md5 file hash.
my code is
from PIL import Image
import hashlib
import os
import sys
import io
img_file = urllib.request.urlopen(img_url, timeout=30)
f = open('C:\\Users\\user\\Documents\\ + img_name, 'wb')
f.write(img_file.read())
f.close # subject image, status = ok
im = Image.open('C:\\Users\\user\\Documents\\ + img_name)
m = hashlib.md5() # get hash
with io.BytesIO() as memf:
im.save(memf, 'PNG')
data = memf.getvalue()
m.update(data)
md5hash = m.hexdigest() # hash done, status = ok
im.close()
if md5hash in hash_list[name]: # comparing hash
os.remove('C:\\Users\\user\\Documents\\ + img_name) # delete file, ERROR
else:
hash_list[name].append(m.hexdigest())
and i get this error
PermissionError: [WinError 32] The process cannot access the file because it is being used by another process:
'C:\\Users\\user\\Documents\\myimage.jpg'
I tried admin command prompt, but still getting this error. Could you find what is accessing the file?

Just noticed you're using f.close instead of f.close()
Add () and check if problem still occurs.
Cheers ;)

Your issue has indeed been as Adrian Daniszewski said, however, there are quite few more programming problems with your code.
First of all, you should familiarize yourself with with. You use with for BytesIO() but it can also be used for opening files.
The benefit of with open(...) as f: is the fact that you don't have to search whether you closed the file or remember to close it. It will close the file at the end of its indentation.
Second, there is a bit of duplication in your code. Your code should be DRY to avoid being forced to change multiple locations with the same stuff.
Imagine having to change where you save the byte files. Right now you will be forced to change in three different locations.
Now imagine not noticing one of these locations.
My suggestion would be first of all to save the path to a variable and use that -
bytesimgfile = 'C:\\Users\\user\\Documents\\' + img_name
An example to use with in your code would be like this:
with open(bytesimgfile , 'wb') as f:
f.write(img_file.read())
A full example with your given code:
from PIL import Image
import hashlib
import os
import sys
import io
img_file = urllib.request.urlopen(img_url, timeout=30)
bytesimgfile = 'C:\\Users\\user\\Documents\\' + img_name
with open(bytesimgfile , 'wb'):
f.write(img_file.read())
with Image.open(bytesimgfile) as im:
m = hashlib.md5() # get hash
with io.BytesIO() as memf:
im.save(memf, 'PNG')
data = memf.getvalue()
m.update(data)
md5hash = m.hexdigest() # hash done, status = ok
if md5hash in hash_list[name]: # comparing hash
os.remove(bytesimgfile) # delete file, ERROR
else:
hash_list[name].append(m.hexdigest())

Related

Python3 - Cannot import local module due to FileNotFoundError

Within my code I am attempting to import modules written by myself. Said modules interact with files on the system, either encrypting, decrypting or removing them altogether. When trying to import these modules I receive the below:
FileNotFoundError: [Errno 2] No such file or directory: <Directory>
Oddly this error seems to appear before anything local within the file runs (calls are at the end), making me believe python is parsing the files during the import phase and not find the files (apologies but I am novice when it comes to importing self created stuff)
Below is one of the methods I am importing (also the one flagging the error)
import urllib.request, re, os
def getKey(url, path):
urllib.request.urlretrieve(url, 'C:\\code\\'+path)
def readFiles(keyFile, targetFile, outfile):
infile = keyFile # read in the input file name
infd = open('C:\\code\\'+infile,"r") # open the file and create the file descriptor infd
key = infd.read( )
key = key.strip('\n')
#print('key= '+key)
infile = targetFile
infd = open('C:\\code\\'+infile, "r")
ptext = infd.read( ).strip('\n')
infd.close
xor(outfile, ptext, key)
def xor(outfile, ptext, key):
outfd = open('C:\\code\\'+outfile, "w")
pLength = len(ptext)
#get the length of the plaintext and cut the key into the same size
keyChunks = [key[i:i+pLength] for i in range(0, len(key), pLength)]
i = 0
while i < len(keyChunks):
a = int(ptext)
b = int(keyChunks[i])
out = a ^ b
i=i+1
outfd = open('C:\\code\\'+outfile, "w")
outfd.write(str(out))
outfd.close
def cleanup(targetFile):
os.remove(targetFile)
def enc():
outfile = 'affk.xor'
getKey('http://192.168.56.10/sym.key', 'sym.key')
readFiles('sym.key', 'affk.txt', outfile)
cleanup('C:/code/affk.txt')
def dec():
outfile = 'affk.txt'
getKey('http://192.168.56.10/sym.key', 'sym.key')
readFiles('sym.key', 'affk.xor', outfile)
cleanup('C:/code/affk.xor')
cleanup('C:/code/sym.key')
enc()
#dec()
Below is a snippet of my main file with the imports and calling function
import os, math, affine, re, urllib.request, ctypes
from xor import enc
from rsa1 import run
---Additional Code here---
def main():
# Call function to search for the files we want to encrypt
search()
# Call function to read the target files. Main ciphers are daisy chained off reader function
reader(targets)
# Call function to XOR Affine cipher key
xor.enc()
# Call function to encrypt key used for above XOR using RSA
rsa1.run()
Any assistance with this problem would be greatly appreciated! Apologies if this is an extremely dumb question!

Troubleshoot a simple checksum comparison script

I have created a simple checksum script that checks a checksum of a file called tecu.a2l and compares it to a few .md5 files - ensuring that they all have the exact same checksum whenever this script is running.
To make things easier to understand:
Lets say i have tecu.a2l with the checksum 1x2x3x. So the md5 files (if generated correctly) should have the same checksum (1x2x3x). If one of the md5 files has a different checksum than what the latest tecu.a2l has it will give an error.
Hopefully the code might fill in the blanks if you did not quite understand my description.
import hashlib
import dst_creator_constants as CONST
import Tkinter
path_a2l = 'C:<path>\tecu.a2l'
md5 = hashlib.md5()
blocks = 65565
with open(path_a2l, 'rb') as a2l:
readA2L = a2l.read(blocks)
generatedMD5 = md5.hexdigest()
print "stop1"
ihx_md5_files = CONST.PATH_DELIVERABLES_DST
for file in ihx_md5_files:
print "stop2"
if file.endswith('.md5'):
print "stop3"
readMD5 = file.read()
if compare_checksums:
print "Yes"
# Add successful TkInter msg here
else:
print "No"
# Add error msg here
def compare_checksums(generatedMD5, readMD5):
if generatedMD5 == readMD5:
return True
else:
return False
When i run this script, nothing happens. No messages, nothing. If i type in python checksum.py into cmd - it returns no message. So i put in some print statements to see what could be the issue. The issue is, that stop3 is never shown in the command prompt - which means that the problem has something to do with if file.endswith('.md5'): statement.
I have no idea why it's the culprit as I have used this file.endswith() statement on a previous script I wrote in relation to this and there it has worked so I am turning to you.
You are not creating a hash object. Your file stays in your readA2L variable. Also, your file may be larger than the 65565 byte buffer you allow it. Try to update your hasher like the function below and let us know what the result is.
import hashlib as h
from os.path import isfile
hasher = h.md5()
block_size = 65536
def get_hexdigest(file_path, hasher, block_size):
if isfile(file_path):
with open(file_path, 'rb') as f:
buf = f.read(block_size)
while len(buf) > 0:
# Update the hasher until the entire file has been read
hasher.update(buf)
buf = f.read(block_size)
digest = hasher.hexdigest()
else:
return None
return digest

Python reportlab save with canvas to specified location

I am wondering how I can make my script save to the Desktop. Here's my code:
from reportlab.pdfgen import canvas
from reportlab.lib.pagesizes import letter
from reportlab.platypus import Image
import csv
import os
data_file = "hata.csv"
def import_data(data_file):
inv_data = csv.reader(open(data_file, "r"))
for row in inv_data:
var1 = row[0]
# do more stuff
pdf_file = os.path.abspath("~/Desktop/%s.pdf" % var1)
generate_pdf(variable, pdf_file)
def generate_pdf(variable, file_name):
c = canvas.Canvas(file_name, pagesize=letter)
# do some stuff with my variables
c.setFont("Helvetica", 40, leading=None)
c.drawString(150, 2300, var1)
c.showPage()
c.save()
import_data(data_file)
So this works perfectly, and it saves/creates the PDF I want -- but in the directory of the script. I would instead like to save it to, say, the Desktop.
When I researched and found os.path.abspath, I thought I solved it; but I receive the following error
File "/usr/local/lib/python3.4/site-packages/reportlab/pdfbase/pdfdoc.py", line 218, in SaveToFile
f = open(filename, "wb")
FileNotFoundError: [Errno 2] No such file or directory: '/Users/TARDIS/Desktop/tests/~/Desktop/00001.pdf'
which tells me that it's trying to save starting from my script's home folder. How do I get it to see outside of that?
After much trial and error using different methods that all had drawbacks, I came up with a solution and figured I'd post it here for posterity. I'm rather new to programming so apologies if this is obvious to the more experienced.
First, I give my pdf file a name:
pdf_name = number + ".pdf"
Then, I find the path to the Desktop for current user (given that I don't know what the user name will be, which was the original root of the problem) and create a path to it so that the pdf can be to be saved there.
save_name = os.path.join(os.path.expanduser("~"), "Desktop/", pdf_name)
Finally, that's passed in to my pdf generation function:
...
save_name = ....
generate_pdf(variable, save_name)
def generate_pdf(variable, save_name):
c = canvas.Canvas(save_name, pagesize=letter)
....
And that's it.

Image handling in Python with Numpy

We are importing an screen capture from a web page direct into a variable in Python; and then producing a Numpy array using the following code :
To capture is a PNG image (note - the device url has an embedded cgi to do the capture work) :
response = requests.get(url.format(ip, device), auth=credentials)
Once screen is captured, covert to a Numpy array called image :
image = imread(BytesIO(response.content))
After analysis of image, we would like to FTP the captured PNG to a server for reference at a later date. The best solution we can find right now involves using imsave to create a file locally and then FTP with storbinary to take the local image and put it on the server.
Is it possible to FTP response.content; or a conversion of the numpy array back into a PNG (using imsave?) direct to the server and skip the local storage step?
Update
As per MattDMo comment, we tried:
def ftp_artifact (ftp_ip, ftp_dir, tid, artifact_name, artifact_path, imgdata) :
ftp = FTP(ftp_ip)
ftp.login("autoftp","autoftp")
ftp.mkd ("FTP/" + ftp_dir)
ftp.cwd("FTP/" + ftp_dir)
filepath = artifact_path
filename = artifact_name
f = BytesIO(imgdata)
ftp.storbinary ('STOR ' + filename, f)
ftp.quit()
Where imgdata is the result of io.imread. The result file is 5x bigger and not an image. The BytesIO object is the numpy array I presume?
In the ftplib module, the FTP.storbinary() method takes an open file object as its second argument. Since your BytesIO object can act as a file object, all you'd need to do is pass that - no need for a temporary file on the server.
EDIT
Without seeing your full code, what I suspect is happening is that you are passing the NumPy array to storbinary(), not the BytesIO object. You also need to make sure the object's read pointer is at the beginning by calling bytesio_object.seek(0) before uploading. The following code demonstrates how to do everything:
from ftplib import FTP
from io import BytesIO
import requests
r = requests.get("http://example.com/foo.png")
png = BytesIO(r.content)
# do image analysis
png.seek(0)
ftp = FTP("ftp.server.com")
ftp.login(user="username", passwd="password")
# change to desired upload directory
ftp.storbinary("STOR " + file_name, png)
try:
ftp.quit()
except:
ftp.close()
Took a bit of research but our student figured it out :
def ftp_image_to(ftp_ip, ftp_dir, filename, data):
ftp = FTP(ftp_ip)
print("logging in")
ftp.login('autoftp', 'autoftp')
print("making dir")
ftp.mkd('FTP/' + ftp_dir)
ftp.cwd('FTP/' + ftp_dir)
print("formatting image")
bytes = BytesIO()
plt.imsave(bytes, data, format='png')
bytes.seek(0)
print("storing binary")
ftp.storbinary('STOR ' + filename, bytes)
ftp.quit()
Thanks IH!

IOError: [Errno 2] No such file or directory, but file does exist

I keep getting an IO Error stating my directory doesn't exist. What am I doing wrong?
I have this in a separate file named pirate.py:
with open("/images/image.jpg", "rb") as fin:
image_data = fin.read()
with open("pirate.py","wb") as fout:
fout.write("image_data="+repr(image_data))
And then the code in my main file
from pirate import image_data
# Content-type declaration
print('Content-type: text/html\n')
def main():
print('<!doctype html><head><meta charset="utf-8">')
print('<style>html {background:url (data:image/gif;base64,' + pirate.image_data + ')
I'm trying to encode an image in base64 and then use it as a background in a .cgi, I'm sure the rest of my code is working, what am I doing wrong here?
try to use absolute file paths. or use root prefix ROOT_PATH = os.path.dirname(os.path.realpath(file))
repr is not what you want, you are saying the image data is base64 ... so make it base 64
with open("pirate.py","wb") as fout:
fout.write("image_data="+base64.b64encode(image_data))
then in addition you say
from pirate import image_data
then you reference it as
pirate.image_data
when you should just reference it as
image_data
theres probably some other probelems since the image image path you show is not the image path from your comment
Your code says
open("/images/image.jpg", "rb")
I suspect the "/" at the beginning is the problem. Or is your images folder in your root?

Categories