Unable to create zip file using python 3 - python-3.5

zip file creation works fine with python2 when i run same code for python 3 created zip file is not a proper zip (i.e when i do unzip storage_aligned.zip) it throws error as
Archive: storage_aligned.zip
End-of-central-directory signature not found. Either this file is not
a zipfile, or it constitutes one disk of a multi-part archive. In the
latter case the central directory and zipfile comment will be found on
the last disk(s) of this archive.
unzip: cannot find zipfile directory in one of storage_aligned.zip or
storage_aligned.zip.zip, and cannot find storage_aligned.zip.ZIP, period
Code Snippet:
aligned_zf = zipfile.ZipFile(file, 'w')
for zinfo in self.filelist:
zef_file = self.fp
zef_file.seek(zinfo.header_offset, 0)
fheader = zef_file.read(zipfile.sizeFileHeader)
if fheader[0:4] != zipfile.stringFileHeader:
raise BadZipfile("Bad magic number for file header")
fheader = struct.unpack(zipfile.structFileHeader, fheader)
fname = zef_file.read(fheader[zipfile._FH_FILENAME_LENGTH])
if fheader[zipfile._FH_EXTRA_FIELD_LENGTH]:
zef_file.read(fheader[zipfile._FH_EXTRA_FIELD_LENGTH])
if fname.decode('utf-8') != zinfo.orig_filename:
raise zipfile.BadZipfile('File name in directory "%s" and header "%s" differ.' % (
zinfo.orig_filename, fname))
# For the first entry, prepend some extraneous bytes before the LFH. This
# is acceptable since ZIP implementations use the CD (end of the file) to
# find entries. Therefore these bytes are ignored
if padding_index == 0:
if sys.version[:1] == '2':
aligned_zf.fp.write(bytes("\0"*paddings[padding_index]))
elif sys.version[:1] == '3':
aligned_zf.fp.write(bytes("\0"*paddings[padding_index], 'utf-8') )
padding_index += 1
# if required, add padding after the file data. This is acceptable as the CD
# references offsets to the LFHs. Therefore extraneous data is ignored and not processed
# orig: aligned_zf.writestr(zinfo, self.read(fname)+'\0'*paddings[padding_index])
aligned_zf.writestr(zinfo, self.read(fname.decode('utf-8')))
if sys.version[:1] == '2':
aligned_zf.fp.write('\0'*paddings[padding_index])
elif sys.version[:1] == '3':
aligned_zf.fp.write(bytes('\0'*paddings[padding_index], 'utf-8'))
padding_index+=1
aligned_zf.close()

Related

Python Paramiko, PermissionError: [Errno 13] Permission denied

There is a daemon that goes to a remote server and fetches files from it. Then performs operations on them. Some files it picks up without any problems. But it gives an error on one of them. I can't figure out why. The file extensions are identical.
Error on a file that was previously uploaded to the save folder. There were no other files in the save folder, so it works correctly. How do I get around this error so that sftp_client will update the file if it is already in the directory?
....
ssh = paramiko.SSHClient()
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy)
try:
ssh.connect(hostname=ip, username=user_name, password=passwd)
except Exception:
logger.info("Server is not available, check that the data entered is correct")
sys.exit()
sftp_client = ssh.open_sftp()
path_serv = '/home/lacit/defect_storage/' # Путь по которому производится поиск файлов
path_serv_file = sftp_client.listdir_attr(path=path_serv) # Все файлы в по данному пути
if path_serv_file:
for entry in path_serv_file:
checking_number = os.path.splitext(entry.filename)[0] # Split .png
try:
id_file_name = int(checking_number) # Checking for number
logger.info(f"Name of scan - {id_file_name}")
except ValueError:
logger.info(f"The scan name must have a numeric value \n Name of scan : {checking_number}")
sys.exit()
sftp_client.get(path_serv + entry.filename, '/home/ubuntu/media/' + entry.filename)
# Сохранение пути файла
path_file_save = '/home/ubuntu/media/' + entry.filename
# Переменная обновления даты
update_date = datetime.datetime.now()
logger.info(f"Try to save or update data for leather - {id_file_name}")
Defect.objects.update_or_create(id_leather=id_file_name,
defaults={'update': update_date,
'result_auto': None,
'result_manual': None,
'path': path_file_save})
logger.info("Try to call defection_start")
....
An error in the line sftp_client.get(path_serv + entry.filename, '/home/ubuntu/media/' + entry.filename)
Screenshot from the console

How do I get my Python script to work on a networked file?

I am working on a script to read the creation date from a source file and change the creation dates on the destination files to match it.
It reads the creation dates for files stored locally and on the NAS.
It changes the creation dates for files stored locally.
However, I can't get it to change the creation dates for files stored on the NAS. I don't get an error message, it just doesn't change the creation date.
Any ideas of how I can get this to work? Or will I have to copy the files to a local folder, make the changes, then copy them back?
creation_dates.py
# Get Creation Date of source file
def get_creeation_date(fn):
return time.ctime(os.path.getctime(fn))
# Convert datetime to integer (for conversion)
def convert_to_integer(dt_time_str):
dt_time = datetime.strptime(dt_time_str, "%a %b %d %H:%M:%S %Y")
return int(datetime.timestamp(dt_time))
# Change the creation date of the destination files based on the source file
# Working with module from this post: >>https://stackoverflow.com/q/47839248/11792868
def changeFileCreationTime(fname, newtime_int):
wintime = pywintypes.Time(newtime_int)
winfile = win32file.CreateFile(
fname,
win32con.GENERIC_WRITE,
win32con.FILE_SHARE_READ
| win32con.FILE_SHARE_WRITE
| win32con.FILE_SHARE_DELETE,
None,
win32con.OPEN_EXISTING,
win32con.FILE_ATTRIBUTE_NORMAL,
None,
)
win32file.SetFileTime(winfile, wintime, None, None)
winfile.close()
def main(fn_src, fn_dest):
changeFileCreationTime(fn_dest, convert_to_integer(get_creeation_date(fn_src)))
if __name__ == "__main__":
file_src = r"\\path\to\source\file 1.mp4" # Located in NAS folder
file_src_dir, file_src_name_ext = os.path.split(file_src)
file_src_name, file_src_ext = os.path.splitext(file_src_name_ext)
file_dest_jpg_1 = re.sub(r"(\s\d$|$)", " 2.jpg", file_src_name, 1) # file to be created to local folder
file_dest_jpg_2 = "\\\\path\\to\\source\\" + file_src_name + "2.jpg" # file to be created to NAS folder
# Also tried r"\\path\to\source\" + file_src_name + "2.jpg"
if os.path.exists(file_dest_jpg_1) == False:
with open(file_dest_jpg_1, "w"):
pass
if os.path.exists(file_dest_jpg_2) == False:
with open(file_dest_jpg_2, "w"):
pass
main(file_src, file_dest_jpg_1) # This works
main(file_src, file_dest_jpg_2) # This does not work

Python3 decode removes white spaces when should be kept

I'm reading a binary file that has a code on STM32. I placed deliberate 2 const strings in the code, that allows me to read SW version and description from a given file.
When you open a binary file with hex editor or even in python3, you can see correct form. But when run text = data.decode('utf-8', errors='ignore'), it removes a zeros from the file! I don't want this, as I keep EOL characters to properly split and extract string that interest me.
(preview of the end of the data variable)
Svc\x00..\Src\adc.c\x00..\Src\can.c\x00defaultTask\x00Task_CANbus_receive\x00Task_LED_Controller\x00Task_LED1_TX\x00Task_LED2_RX\x00Task_PWM_Controller\x00**SW_VER:GN_1.01\x00\x00\x00\x00\x00\x00MODULE_DESC:generic_module\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00**Task_SuperVisor_Controller\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x02\x03\x04\x06\x07\x08\t\x00\x00\x00\x00\x01\x02\x03\x04..\Src\tim.c\x005!\x00\x08\x11!\x00\x08\x01\x00\x00\x00\xaa\xaa\xaa\xaa\x01\x01\nd\x00\x02\x04\nd\x00\x00\x00\x00\xa2J\x04'
(preview of text, i.e. what I receive after decode)
r g # IDLE TmrQ Tmr Svc ..\Src\adc.c ..\Src\can.c
defaultTask Task_CANbus_receive Task_LED_Controller Task_LED1_TX
Task_LED2_RX Task_PWM_Controller SW_VER:GN_1.01
MODULE_DESC:generic_module
Task_SuperVisor_Controller ..\Src\tim.c 5! !
d d J
with open(path_to_file, "rb") as binary_file:
# Read the whole file at once
data = binary_file.read()
text = data.decode('utf-8', errors='ignore')
# get index of "SW_VER:" sting in the file
sw_ver_index = text.rfind("SW_VER:")
# SW_VER found
if sw_ver_index is not -1:
# retrive the value, e.g. "SW_VER:WB_2.01" will has to start from position 7 and finish at 14
sw_ver_value = text[sw_ver_index + 7:sw_ver_index + 14]
module.append(tuple(('DESC:', sw_ver_value)))
else:
# SW_VER not found
module.append(tuple(('DESC:', 'N/A')))
# get index of "MODULE_DESC::" sting in the file
module_desc_index = text.rfind("MODULE_DESC:")
# MODULE_DESC found
if module_desc_index is not -1:
module_desc_substring = text[module_desc_index + 12:]
module_desc_value = module_desc_substring.split()
module.append(tuple(('DESC:', module_desc_value[0])))
print(module_desc_value[0])
As you can see my white characters are gone, while they should be present

Linecache getline does not work after my application was installed

I am creating a tool that gives an overview of hundredths of test results. This tool access a log file, checks for Pass and Fail verdicts. When it is a fail, I need to go back to previous lines of the log to capture the cause of failure.
The linecache.getline works in my workspace (Python Run via eclipse). But after I created a windows installer (.exe file) and installed the application in my computer, the linecache.getline returns nothing. Is there something I need to add into my setup.py file to fix this or is it my code issue?
Tool Code
precon:
from wx.FileDialog, access the log file
self.result_path = dlg.GetPath()
try:
with open(self.result_path, 'r') as file:
self.checkLog(self.result_path, file)
def checkLog(self, path, f):
line_no = 1
index = 0
for line in f:
n = re.search("FAIL", line, re.IGNORECASE) or re.search("PASS", line, re.IGNORECASE)
if n:
currentline = re.sub('\s+', ' ', line.rstrip())
finalresult = currentline
self.list_ctrl.InsertStringItem(index, finaltestname)
self.list_ctrl.SetStringItem(index, 1, finalresult)
if currentline == "FAIL":
fail_line1 = linecache.getline(path, int(line_no - 3)) #Get reason of failure
fail_line2 = linecache.getline(path, int(line_no - 2)) #Get reason of failure
cause = fail_line1.strip() + " " + fail_line2.strip()
self.list_ctrl.SetStringItem(index, 2, cause)
index += 1
line_no += 1
The issue was resolved by doing the get_line function from this link:
Python: linecache not working as expected?

Error in using os.path.walk() correctly

So I created this Folder C:\TempFiles to test run the following code snippet
Inside this folder i had two files -> nd1.txt, nd2.txt and a folder C:\TempFiles\Temp2, inside which i had only one file nd3.txt
Now when i execute this code:-
import os,file,storage
database = file.dictionary()
tools = storage.misc()
lui = -1 # last used file index
fileIndex = 1
def sendWord(wrd, findex): # where findex is the file index
global lui
if findex!=lui:
tools.refreshRecentList()
lui = findex
if tools.mustIgnore(wrd)==0 and tools.toRecentList(wrd)==1:
database.addWord(wrd,findex) # else there's no point adding the word to the database, because its either trivial, or has recently been added
def showPostingsList():
print("\nPOSTING's LIST")
database.display()
def parseFile(nfile, findex):
for line in nfile:
pl = line.split()
for word in pl:
sendWord(word.lower(),findex)
def parseDirectory(dirname):
global fileIndex
for root,dirs,files in os.walk(dirname):
for name in dirs:
parseDirectory(os.path.join(root,name))
for filename in files:
nf = open(os.path.join(root,filename),'r')
parseFile(nf,fileIndex)
print(" --> "+ nf.name)
fileIndex+=1
nf.close()
def main():
dirname = input("Enter the base directory :-\n")
print("\nParsing Files...")
parseDirectory(dirname)
print("\nPostings List has Been successfully created.\n",database.entries()," word(s) sent to database")
choice = ""
while choice!='y' and choice!='n':
choice = str(input("View List?\n(Y)es\n(N)o\n -> ")).lower()
if choice!='y' and choice!='n':
print("Invalid Entry. Re-enter\n")
if choice=='y':
showPostingsList()
main()
Now I should Traverse the three files only once each, and i put a print(filename) to test that, but apparently I am traversing the inside folder twice:-
Enter the base directory :-
C:\TempFiles
Parsing Files...
--> C:\TempFiles\Temp2\nd3.txt
--> C:\TempFiles\nd1.txt
--> C:\TempFiles\nd2.txt
--> C:\TempFiles\Temp2\nd3.txt
Postings List has Been successfully created.
34 word(s) sent to database
View List?
(Y)es
(N)o
-> n
Can Anyone tell me how to modify the os.path.walk() as such to avoid the error
Its not that my output is incorrect, but its traversing over one entire folder twice, and that's not very efficient.
Your issue isn't specific to Python 3, it's how os.walk() works - iterating already does the recursion to subfolders, so you can take out your recursive call:
def parseDirectory(dirname):
global fileIndex
for root,dirs,files in os.walk(dirname):
for filename in files:
nf = open(os.path.join(root,filename),'r')
parseFile(nf,fileIndex)
print(" --> "+ nf.name)
fileIndex+=1
nf.close()
By calling parseDirectory() for the dirs, you were starting another, independant walk of your only subfolder.

Resources