XLRD/Python: Encrypte Excel or make exception - python

I need to go through the subdirectories of a given directory, search for excel files and then read their sheet names. A problem occurs when the loop finds an encrypted file. I tried to read files with xlrd and pandas. But I get an error:
xlrd.XLRDError Workbook is encrypted
I made an exception with pass method, but if I do so, the loop breaks at this point and the program stops. What do I have to do to pass that error and move on to the next file? Is there any method to check if the file is encrypted before the method xlrd.open_workbook which collapses the program? Or is it possible to make an exception where I could pass the error and move on?
import codecs
import xlrd
import os
import Tkinter
import tkFileDialog
def pyrexcel(path,file,list):
print 'do now: ' + path + '/' + file
workbook = xlrd.open_workbook(path + '/' + file, encoding_override='windows-1250')
sheet_names = workbook.sheet_names()
for sheet in sheet_names:
list.append(path+"/"+file+"/"+sheet)
def finder(destin,listka,list):
for pliczek in os.listdir(destin):
if os.path.isdir(destin +"/" +pliczek):
finder(destin +"/" +pliczek,listka,list)
elif pliczek[-4:] == ".xls":
pyrexcel(destin,pliczek,list)
elif pliczek[-4:] == ".rar" or pliczek[-4:] == ".zip":
listka.append(destin+pliczek)
root = Tkinter.Tk()
root.withdraw()
listaExcel = []
listaZip = []
dirname = tkFileDialog.askdirectory(parent=root, initialdir="/", title='choose dir to iterate')
print "you choose: " + dirname
try:
finder(dirname,listaZip,listaExcel)
except xlrd.XLRDError as e:
print e.message
pass
plik = codecs.open((dirname + "/listaZIP.txt"), 'w', "utf-8")
for item in listaZip:
plik.write("%s\n" % item)
plik.close()
plik = codecs.open((dirname + "/listaExcel.txt"), 'w', "utf-8")
for item in listaExcel:
plik.write("%s\n" % item)
plik.close()

continue should accomplish what you want as listed here:
"pass simply does nothing, while continue goes on with the next loop iteration. In your example, the difference would become apparent if you added another statement after the if: After executing pass, this further statement would be executed. After continue, it wouldn't."
Also I found this answer while trying to look for a way to find out if an Excel file is encrypted via python so thank you! :D
Source: Is there a difference between `continue` and `pass` in a for loop in python?
Python Docs: https://docs.python.org/2/reference/simple_stmts.html#continue

Related

Is there a way to put the main.py file into a folder?

I have been working on an assignment with several text files, but an getting the file not found error. I was told to put all the text files into a folder as well as the main program. How can I put the main.py file into a folder with the rest of the files?
Code:
def main():
process_file("good_data.txt")
process_file("bad_data.txt")
process_file("empty_file.txt")
process_file("does_not_exist.txt")
def process_file(param_str_file_name):
#Variables
num_rec = 0
total = 0
average = 0
try:
file_name = open('param_str_file_name', 'r')
print("Processing file", file_name)
variable = file_name.readline()
while variable != "":
file_name_int = int(file_name)
num_rec = num_rec + 1
variable = file_name.readline()
total += file_name_int
average = total / num_rec
file_name.close()
print("\tRecord count = ", num_rec)
print("\tTotal = ", total)
print("\tAverage = " , f"{average:.2f}", "\n")
except EOFError:
print("\tError!", param_str_file_name, " is empty. Cannot calculate average\n")
except FileNotFoundError:
print("\tError!", param_str_file_name, " File not found\n")
except ValueError:
print("\tError!", param_str_file_name, "contains non-numeric data\n")
if __name__ == "__main__":
main()
Thanks for the help guys
Problem #1
This may have nothing to do with your code, but just move your main.py file into the same folder as your text files.
If you want to keep your text files in a different directory however, try using this code:
import os
os.chdir('/path/to/the/folder')
This will change where your program looks. This is called change directory (also known as cd or chdir).
Problem #2
You use "param_str_file_name" as a string instead of using the argument in the
file_name = open('param_str_file_name', 'r')
line.
With most text editors, you can simply create a file in a folder, or you could drag a code file into a folder.

Get file details (complete file path) from the filename (only basename) existing as a text in tkinter Text widget

With the help of following code I am inserting the filename (file basename) in the tkinter Text widget and subsequently then trying to print the complete file path after the "Get Data" button is pressed.
import tkinter as tk
from tkinter.filedialog import askopenfilename
import os
root=tk.Tk()
ent=tk.Text(root)
ent.grid(row=1,column=0)
def addfile():
filename =askopenfilename(filetypes=(("Tiff files","*.tif"),("All files","*.*")))
ent.insert(tk.INSERT, '"' + os.path.basename(filename) + '"')
ent.insert(tk.INSERT, "\n")
def getfile():
print(ent.get("1.0", tk.END))
b=tk.Button(root,text="Select File",command=addfile)
b.grid(row=0,column=0)
b1 = tk.Button(root,text="Get Data",command=getfile)
b1.grid(row=2,column=0)
root.mainloop()
After running the above code only filenames are getting printed (without filepath).
Now basically what I want is that, after the "Get Data" button is pressed (where the contents of Text widget is read) then complete path of files should be printed.
Additional information:-
I know that if filenames would have been different then I could have used dictionary (key, value) pair to link basename of each file with its absolute path. But issue will come when different files present in different folder location but having same names are added to the Text widget.
As Cool Cloud has commented it is hard to give the exact answer you need, because you havent told us what is happening and what you expect/what to happen.
The way I read it is that you either want:
the whole filename, which you have recieved from the askopenfilename() to be inserted in the Text widget.
you want the whole filename to be printed when you click the Button b1, but the Text widget to be left as is.
1. I would change def addfile(): to
def addfile():
filename = askopenfilename()
ent.insert(tk.INSERT, '"' + filename + '"\n')
What this does is inserts the full file path rather than just the basename, i.e. it would insert "D:/example/help.tif" rather than just help.tif.
2. I would use the code below
root = tk.Tk()
def addfile():
filename = askopenfilename()
list_of_filenames.append(filename)
ent.insert(tk.INSERT, '"' + os.path.basename(filename) + '"\n')
def getfile():
for i in range(len(list_of_filenames)):
print(list_of_filesnames[i])
list_of_filenames = []
ent = tk.Text(root)
ent.grid(row=1, column=0)
b=tk.Button(root,text="Select File",command=addfile)
b.grid(row=0,column=0)
b1 = tk.Button(root,text="Get Data",command=getfile)
b1.grid(row=2,column=0)
root.mainloop()
What I have done is create a global list variable named list_of_filenames and in def addfile(): I added the line list_of_filenames.append(filename), this takes the file you selected, and the path, and add it to the list variable. Thus giving you a list with every file you select, and it can be accessed by any function you build because it is global.
The final change is to def getfile(): this can be done exactly how you would like to, I have written it to print each of the files individually on a seperate lines, without square brackets or quotation marks.
Using the same example as in part 1, if I selected a file with the path D:/example/help.tif the Text widget would read "help.tif" and when b1 is clicked D:/example/help.tif would be printed to the consol.
I will split my code up to try and explain what i've done.
The first 4 functions are to do the addfile(): plus the other thing you have asked for.
The first function split_filename(path): does what the fuction name says. It will take the path entered and create a list of the individual parts of the the path. (i.e. if you have D:/folder/example/help/test.tif it would return ['D:/', 'folder', 'example', 'help', 'test.tif'], you will see later that this is useful when you have 2 basenames that are the same.
def split_filename(path):
allParts = []
while 1:
parts = os.path.split(path)
if parts[0] == path:
allParts.insert(0, parts[0])
break
elif parts[1] == path:
allParts.insert(0, parts[1])
break
else:
path = parts[0]
allParts.insert(0, parts[1])
return allParts
check_if_fileBasename_in_current_content(current_content, selected_file_basename): again the function name tells you exactly what is does. This checks if the new selected file basename is already in the Text widget.
def check_if_fileBasename_in_current_content(current_content, selected_file_basename):
for line in current_content:
if line == '':
pass
elif line == selected_file_basename:
return True
The third if_true_split_path_for_basename(selected_file_path, selected_file_basename): is called if the new selected file basename already exists in the Text widget. The fuction takes the path for both the new selected file and the 1 already saved. If you have 2 files: D:/example1/help.tif(new selected) and D:/example2/help.tif(previously added) the new selected basename would become example2/help.tif instead of just help.tif. By doing this it makes it possible to distiquish the difference between the 2 files. At the end of the fuction the basename created thought the fuction is inserted into ent and added to the dictionary dict_of_filenames(this become useful when printing the paths when b1 is clicked.)
def if_true_split_path_for_baseline(selected_file_path, selected_file_basename):
basename_for_text_widget = []
if selected_file_path in dict_of_filenames:
pass
else:
for path, basename in dict_of_filenames.items():
if basename == selected_file_basename:
duplicate_path_split = split_filename(path)
selected_file_path_split = split_filename(selected_file_path)
for i in range(len(selected_file_path_split)):
duplicate_slice = duplicate_path_split[-(i + 1)]
selected_slice = selected_file_path_split[-(i + 1)]
if duplicate_slice == selected_slice:
basename_for_text_widget.insert(0, selected_slice)
else:
basename_for_text_widget.insert(0, selected_slice)
break
ent.insert(tk.INSERT, str('/'.join(basename_for_text_widget) + '\n'))
dict_of_filenames.update({selected_file_path: '/'.join(basename_for_text_widget)})
addFile() link all of the functions above, it: ask for a file; get the basename; get all of the current text is in the Text widget; checks if the basename already exists and if so call fuction 3 (above), and finally if it is a new basename it inserts the basename to ent and adds both path and basename to the dictionary.
def addFile():
selected_file_path = askopenfilename(filetypes=(("Tiff files", "*.tif"), ("All files", "*.*")))
selected_file_basename = os.path.basename(selected_file_path)
current_content = ent.get("1.0", tk.END).splitlines()
check1 = check_if_fileBasename_in_current_content(current_content, selected_file_basename)
basename_for_text_widget = []
if check1:
if_true_split_path_for_baseline(selected_file_path, selected_file_basename)
else:
basename_for_text_widget.append(selected_file_basename)
dict_of_filenames.update({selected_file_path: ''.join(basename_for_text_widget)})
ent.insert(tk.INSERT, str(' '.join(basename_for_text_widget) + '\n'))
Next is the getFile(): takes the the content of ent and then takes the basename and prints the corresponding path.
def getFile():
current_content = ent.get(1.0, tk.END).splitlines()
for path, basename in dict_of_filenames.items():
if basename in current_content:
print(path)
The final change you need to do is to create the global dictionary
by adding dict_of_filename = {} Insert below the def getFile(): fuction, with no indentation like the Text and Button variables
Everything else stays as is.

Python: How do I scan for a file, if it is not found, then add a new one?

I am trying to make a program that writes a new file each time it runs.
For example:
I run the program once. The folder is empty so it adds a file to the folder named "Test_Number_1.txt"
I run the program for the second time. The folder has one file, so it scans it as a file, scans for another file but there is no file, so it creates a new file named "Test_Number_2.txt"
This is what I had in mind, but the code won't leave the while loop. I am still new to programming so excuse my inefficient coding haha.
memory = # something that changes each time I run the program
print(memory)
print("<-<<----<<<---------<+>--------->>>---->>->")
found_new = False
which_file = 0
while not found_new:
try:
file = open("path_to_folder/Test_Number_" + str(which_file) + ".txt", "a")
except FileNotFoundError:
which_file += 1
file_w = open("path_to_folder/Test_Number_" + str(which_file) + ".txt", "w")
found_new = True
break
print("Looked", which_file, "times.")
which_file += 1
time.sleep(1)
file = open("path_to_folder/Test_Number_" + str(which_file) + ".txt", "a")
file.write(memory)
file.close()
print("Done.")
I put the time.sleep(1) to delay the process in case of a bug so that my entire computer didn't overload and thank goodness because the program just keeps adding more and more files until I force quit it.
One simple solution
from os.path import isfile
def file_n(n):
return "Test_number_" + str(n) + ".txt"
n = 0
while isfile(file_n(n)):
n += 1
f = open( file_n(n), "w" )
f.write("data...")
f.close()
The problem is that if many instances of that same program run at the same time, some files may be overwritten.

python code doesn't generate the csv file [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 5 years ago.
Improve this question
AIM: I wanted to record all of the files on a variety of hard disk and collects the: file name, folders, and size of the file in megabytes. The code runs, to my knowledge doesn't produce any errors, but doesn't produce the csv file at the end?
What I've tried:
I've tried running the file with Sudo, changing the permissions with chmod +x, checking that python is in the same place for standard user and for sudo user, and lastly removing or commenting out troublesome lines which seem to yield different results or errors depending on OS.
import os
from os import path
import sys
import datetime
from datetime import date, time, timedelta
import time
import csv
#from socket import gethostbyname
#variables
#hostname = str(socket.gethostname())
scandir = "/"
savefiledir = "/Users/joshua/Documents/python/"
textfilename = str(datetime.datetime.now().strftime("%Y-%m-%d")) + "_" "directory_printer.csv"
#change directory to the root directory or the one which you want to scan for files (scandir)
os.getcwd()
os.chdir(scandir)
directory = os.getcwd()
#find all files in a directory and it's sub directory regardless of extension
results = [val for sublist in [[os.path.join(i[0], j) for j in i[2]] for i in os.walk(directory)] for val in sublist]
d = {}
file_count = 0
metadata = []
for file in results:
#full path
try:
fullpath = file
except:
fullpath = None
#file name
try:
file_directory = "/".join(str(file).split('/')[1:-1])
except:
file_directory = None
#file extension
try:
file_ext = str(file).split('/')[-1]
except:
file_ext = None
#subfolders
try:
parts = file_directory.split('/')
sub_folders = ":".join(parts[1:-1])
except:
sub_folders = None
#num subfolders
try:
count_subfolders = len(sub_folders.split(':'))
except:
count_subfolders = None
#filesize megabytes
try:
filesize_mb = os.path.getsize(file)/1024
except:
filesize_mb = None
#date modified
try:
date_modified = datetime.datetime.now() - datetime.datetime.fromtimestamp(path.getmtime(file))
except:
date_modified = None
#time modified
#try:
# time_modified = os.stat(fullpath).st_mtime #time of most recent content modification
#except:
# time_modified = None
#time created (windows)
# try:
# time_created = os.stat(fullpath).st_ctime #platform dependent; time of most recent metadata change on Unix, or the time of creation on Windows)# except:
# time_created = None
#record all file metadata
d[file_count] = {'Full_Path': fullpath, 'File_Directory': file_directory,
'File_Extension': file_ext, 'List_Sub_Folders' : sub_folders,
'Count_Sub_Folders' : count_subfolders, 'Filesize_mb' : filesize_mb,
'Date_Modified' : date_modified}
file_count = file_count + 1
#write the dictinary with the disks file metadata to a csv file
with open(textfilename,'w') as f:
w = csv.writer(f)
w.writerows(d.items())
print("Scanning directory: "
+ str(scandir) + " complete!" + "\n"
+ "The results have been saved to: " + "\n"
+ str(savefiledir)+str(textfilename))
As it is, it looks like your code will write the CSV file to scandir (/), not to savefiledir, because at the beginning of the program you call os.chdir(scandir). If you want to get the file at the right place (where the final printed message says it's saved to) you should do:
# ...
#write the dictinary with the disks file metadata to a csv file
with open(savefiledir + textfilename,'w') as f:
w = csv.writer(f)
w.writerows(d.items())
# ...

Passing a relative path in a function

Can someone tell me if the following function declaration is the correct way to pass a relative path to a function? The call is only taking one variable. When I include a second variable (absolute path), my function does not work.
def extract(tar_url, extract_path='.'):
The call that does not work:
extract(chosen, path)
This works, but does not extract:
extract(chosen)
Full Code:
def do_fileExtract(self, line):
defaultFolder = "Extracted"
if not defaultFolder.endswith(':') and not os.path.exists('c:\\Extracted'):
os.mkdir('c:\\Extracted')
raw_input("PLACE .tgz FILES in c:\Extracted AT THIS TIME!!! PRESS ENTER WHEN FINISHED!")
else:
pass
def extract(tar_url, extract_path='.'):
print tar_url
tar = tarfile.open(tar_url, 'r')
for item in tar:
tar.extract(item, extract_path)
if item.name.find(".tgz") != -1 or item.name.find(".tar") != -1:
extract(item.name, "./" + item.name[:item.name.rfind('/')])
userpath = "Extracted"
directory = os.path.join("c:\\", userpath)
os.chdir(directory)
path=os.getcwd() #Set log path here
dirlist=os.listdir(path)
files = [fname for fname in os.listdir(path)
if fname.endswith(('.tgz','.tar'))]
for item in enumerate(files):
print "%d- %s" % item
try:
idx = int(raw_input("\nEnter the file's number:\n"))
except ValueError:
print "You fail at typing numbers."
try:
chosen = files[idx]
except IndexError:
print "Try a number in range next time."
newDir = raw_input('\nEnter a name to create a folder a the c: root directory:\n')
selectDir = os.path.join("c:\\", newDir)
path=os.path.abspath(selectDir)
if not newDir.endswith(':') and not os.path.exists(selectDir):
os.mkdir(selectDir)
try:
extract(chosen, path)
print 'Done'
except:
name = os.path.basename(sys.argv[0])
print chosen
It looks like you missed an escape character in "PLACE .tgz FILES in c:\Extracted AT THIS TIME!!! PRESS ENTER WHEN FINISHED!"
I don't think raw_input sees the prompt string as a raw string, just the user input.
But this shouldn't affect the functionality of your program.
Are you on Unix or windows? I was under the impression that the on Unix you use / forward slash instead of \\ backslash as a separator.
I tested some code on this file:
http://simkin.asu.edu/geowall/mars/merpano0.tar.gz
The following code:
>>> from os import chdir
>>> import tarfile
>>> chdir(r'C:\Users\Acer\Downloads')
>>> tar_url = 'merpano0.tar.gz'
>>> print tar_url
merpano0.tar.gz
>>> tar = tarfile.open(tar_url, 'r')
>>> extract_path = 'C:\\Users\\Acer\\Downloads\\test\\'
>>> for item in tar:
tar.extract(item, extract_path)
executed cleanly with no problems on my end. In the test directory I got a single folder with some files, exactly as in the original tar file. Can you explain what you're doing differently in your code that might be bugging up?

Categories

Resources