directory name created with a weird folder name - python

I have the following code where as part of the code it tries to create a folder if it doesnt exist, I see the folder created with directoryname as "AYH9P4~H",it should be created whatever is in the text file "data_file.txt" which is "AU_1.2.333",any inputs on why it is created with folder name "AYH9P4~H",BTW , running this script on a linux box
import os
def getAU (aufilename):
file = open(aufilename,'r')
return file.read()
def main ():
aufilename="data_file.txt"
#ROOT_DIR - The reference android build used to make the builds
AU=getAU(aufilename)
if (os.path.isdir("/local/mnt/workspace/builds/" + AU)):
print "Direcotry local/mnt/workspace/builds/" + AU + "exists"
else:
print "Directory doesnt exist,creating directory" + AU + "now"
os.chdir("/local/mnt/workspace/builds")
os.makedirs(AU)
ROOT_DIR= "/local/mnt/workspace/builds/" + AU
print "ROOT_DIR"
print ROOT_DIR
if __name__ == '__main__':
main()

My best guess would be, that file.read() actually returns everything including linefeed, and possible other characters. You need to sanitize the output of file.read() in any case.
Other thought is that if you're trying to create such a folder on a filesystem that doesn't support multiple extensions (you have multiple dots in the name) it will be borked too.

Related

How can I open a python shelve file in a specific directory

I am working on Ch. 8 of "Automate the Boring Stuff With Python", trying to extend the Multiclipboard project. Here is my code:
#! /usr/bin/env python3
# mcb.pyw saves and loads pieces of text to the clipboard
# Usage: save <keyword> - Saves clipboard to keyword.
# <keyword> - Loads keyword to the clipboard.
# list - Loads all keywords to clipboard.
# delete <keyword> - Deletes keyword from shelve.
import sys, shelve, pyperclip, os
# open shelve file
dbFile = os.path.join('Users', 'dustin', 'Documents', 'repos', 'python', 'mcbdb')
shelfFile = shelve.open(dbFile)
# Save clipboard content
if len(sys.argv) == 3 and sys.argv[1].lower() == 'save':
shelfFile[sys.argv[2]]= pyperclip.paste()
# Delete choosen content
elif len(sys.argv) == 3 and sys.argv[1].lower() == 'delete':
if sys.argv[2] in list(shelfFile.keys()):
del shelfFile[sys.argv[2]]
print('"' + sys.argv[2] + '" has been deleted.')
else:
print('"' + sys.argv[2] + '" not found.')
elif len(sys.argv) == 2:
# List keywords
if sys.argv[1].lower() == 'list':
print('\nAvailable keywords:\n')
keywords = list(shelfFile.keys())
for key in sorted(keywords):
print(key)
# Load content
elif sys.argv[1] in shelfFile:
pyperclip.copy(shelfFile[sys.argv[1]])
else:
# Print usage error
print('Usage:\n1. save <keyword>\n2. <keyword>\n' +
'3. list\n4. delete <keyword>')
sys.exit()
# close shelve file
shelfFile.close()
I have added this program to my path and would like to use it from whatever directory I am currently working in. The problem is that shelve.open() creates a new file in the current working directory. How can I have one persistent directory?
3 years later and I've stumbled across the same problem.
As you stated
shelfFile = shelve.open('fileName')
saves the shelf file to the cwd. Depending on how you start your script the cwd changes and thus the file may get saved in different places.
Of course you can say
shelfFile = shelve.open('C:\an\absolute\path')
but that's problematic if the original script is moved to another directory.
Therefore I've come up with this:
from pathlib import Path
shelfSavePath = Path(sys.argv[0]).parent / Path('filename')
shelfFile = shelve.open(fr'{shelfSavePath}')
This will save the shelf file in the same directory the python script is in.
Explanation:
On windows sys.argv[0] is the full pathname of the script which will probably look something like this:
C:\Users\path\to\script.py
Look here for documentation on sys.argv
In this example
Path(sys.argv[0]).parent
would result in
C:\Users\path\to
to which we add Path('filename') by using the / Operator.
As a result this would give us:
C:\Users\path\to\filename
and thus always save the shelf file in the same directory as the script regardless of what directory the script is in.
Look here for documentation on pathlib
Your
dbFile = os.path.join('Users', 'dustin', 'Documents', 'repos', 'python', 'mcbdb')
will turn into something like 'Users/dustin/Documents/repos/python/mcbdb' so if you run it from /Users/dustin/ it'll point to /Users/dustin/Users/dustin/Documents/repos/python/mcbdb which is probably not what you want.
If you use an absolute path, something rooted with either / or X:\ (OS-dependent) will keep that "specific directory".
I might recommend something else though, get the user's home directory using ~ and os.path.expanduser:
dbFile = os.path.expanduser('~/.mcbdb')

utime() has no effect in Windows

I have a python script which is supposed to loop through all files in a directory and set the date of each file to the current time. It seems to have no effect, i.e. the Date column in the file explorer shows no change. I see the code looping through all files, it just appears that the call to utime has no effect.
The problem is not this because most of the dates are months old.
# set file access time to current time
#!/usr/bin/python
import os
import math
import datetime
def convertSize(size):
if (size == 0):
return '0B'
size_name = ("B", "KB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB")
i = int(math.floor(math.log(size,1024)))
p = math.pow(1024,i)
s = round(size/p,2)
return '%s %s' % (s,size_name[i])
# see www.tutorialspoint.com/python/os_utime.htm
def touch(fname, times=None):
fhandle = open(fname, 'a')
try:
os.utime(fname, times)
finally:
fhandle.close()
def main():
print ("*** Touch Files ***");
aml_root_directory_string = "C:\\Documents"
file_count = 0
file_size = 0
# traverse root directory, and list directories as dirs and files as files
for root, dirs, files in os.walk(aml_root_directory_string):
path = root.split('/')
#print((len(path) - 1) * '---', os.path.basename(root))
for file in files:
filename, file_extension = os.path.splitext(file)
print(len(path) * '---', file)
touch(filename, )
#
print ("\n*** Total files: " + str(file_count) + " Total file size: " + convertSize(file_size) + " ***");
print ("*** Done: Time: " + str(datetime.datetime.now()) + " - Touch Files ***");
# main ###############################################################################
if __name__ == "__main__":
# stuff only to run when not called via 'import' here
main()
Edit:
In case anyone reads this in the future, it is also important to note the the file explorer can display more than 1 kind of date
You've got three issues:
You're using the file name, not the full path, when touching, so all the touching occurs in the working directory
You're stripping the file extension too, so the touched files lack extensions
You're touching files to which you have an open file handle, and on Windows, on Python 2.7, this is a problem, because os.utime opens the files with no sharing allowed, which is incompatible with existing open file handles
To fix #3, change your touch method to:
def touch(fname, times=None):
# Open and immediately close file to force existence
with open(fname, 'ab') as f:
pass
# Only alter times when file is closed
os.utime(fname, times)
To fix #1 and #2, change your main method to call touch like so:
touch(os.path.join(root, file))
which uses the original name and joins it with the root directory being traversed, where touch(filename) was touching a file without the extension, in the program's working directory (because you used an unqualified name). If you find your program's working directory (print os.getcmd() will tell you where to look), you'll find a bunch of random empty files there corresponding to the files found in the tree you were traversing, stripped of paths and file extensions.
Side-note: If you can move to Python 3 (it's been a while, and there are a lot of improvements), you can make a slightly safer (race-free) and faster touch thanks to file descriptor support in os.utime:
def touch(fname, times=None):
with open(fname, 'ab') as f:
os.utime(f.fileno(), times)
Not all systems will support file descriptors, so if you need to handle such systems, define touch based on testing for file descriptor support via os.supports_fd.
os.utime does work on Windows but probably you are looking at the wrong date in explorer. os.utime does not modify the creation date (which it looks like is what is used in the date field in explorer). It does update the "Date modified" field. You can see this if you right click on the category bar and check the "date modified" box. Alternatively start a command line and type "dir". The date shown there should reflect the change.
I tested os.utime on python 2.7 where you have to give two arguments:
os.utime("file.txt", None)
and on Python 3 where the second argument defaults to None:
os.utime("file.txt")

A pdf file generated from latex code created in a wrong directory - Python

I am currently trying to write a program which opens a latex file and generates a pdf with the same name and saves it in the same folder as the latex file. My problem: The pdf file is created in the same folder as the python file of the program I am running, rather than the folder where the latex file is - I can't get my head around why this is happening. I am trying to achieve my goal in two steps.
First I use a function which takes the directory and the title of the latex file, so that a pdf with the same name can be generated:
def getName(self, somestring):
if "/" in somestring:
indexsofslash = [i for i, ltr in enumerate(somestring) if ltr == "/"]
indexsofdot = [i for i, ltr in enumerate(somestring) if ltr == "."]
lastindexslash = max(indexsofslash)
lastindexdot = max(indexsofdot)
mainName = somestring[lastindexslash + 1:lastindexdot]
pdfDirectory = somestring[:lastindexslash + 1]
someothername = pdfDirectory + mainName
newname = someothername
else:
newname = somestring
return newname
After that I use this function to generate a pdf file, using:
def generate_pdf(self):
name=self.getName(self.fl)
f = open('%s.tex'%name,'w')
tex = self.txt.get(1.0,"end-1c")
f.write(tex)
f.close()
proc=subprocess.Popen(['pdflatex','%s.tex'%name])
proc.communicate()
os.startfile('%s.pdf'%name)
#os.unlink('%s.tex'%name)
os.unlink('%s.log'%name)
os.unlink('%s.aux'%name)
*Note: when name is printed it shows the directory of the latex file + the title of the file, i.e. H:/Public/Test/test.
What happens: A pdf is generated in the folder where the python file of the program I am running is, rather than in the folder where my latex file is - what is it that I am doing wrong?
The problem is that by default pdflatex writes the output files into the current working directory. To alter that behaviour you need to supply an option.
Take a look at the man page of pdflatex:
$ man pdflatex
and search for -output-directory, and you will see:
-output-directory directory
Write output files in directory instead of the current directory. Look up input files in directory first, the along the normal search path.
Thus you will need to modify your python code to something like this:
proc=subprocess.Popen(['pdflatex', '-output-directory', pdfDirectory, '%s.tex' % name])
assuming pdfDirectory is your detination.

Trying to access a file located on a flashdrive

I have made a simple test code in python that reads from a text file, and then preforms an action if the text file contains a line "on".
My code works fine if i run the script on my hardive with the text file in the same folder. Example, (C:\Python27\my_file.txt, and C:\Python27\my_scipt.py).
However, if I try this code while my text file is located on my flashdrive and my script is still on my hardrive it won't work even though I have the correct path specified. Example, (G:\flashdrive_folder\flashdrive_file.txt, and C:\Python27\my_scipt.py).
Here is the code I have written out.
def locatedrive():
file = open("G:\flashdrive_folder\flashdrive_file.txt", "r")
flashdrive_file = file.read()
file.close()
if flashdrive_file == "on":
print "working"
else:
print"fail"
while True:
print "trying"
try:
locatedrive()
break
except:
pass
break
The backslash character does double duty. Windows uses it as a path separator, and Python uses it to introduce escape sequences.
You need to escape the backslash (using a backslash!), or use one of the other techniques below:
file = open("G:\\flashdrive_folder\\flashdrive_file.txt", "r")
or
file = open(r"G:\flashdrive_folder\flashdrive_file.txt", "r")
or
file = open("G:/flashdrive_folder/flashdrive_file.txt", "r")
cd /media/usb0
import os
path = "/media/usb0"
#!/usr/bin/python
import os
path = "/usr/tmp"
# Check current working directory.
retval = os.getcwd()
print "Current working directory %s" % retval
# Now change the directory
os.chdir( path )
# Check current working directory.
retval = os.getcwd()
print "Directory changed successfully %s" % retval
Use:
import os
os.chdir(path_to_flashdrive)

How to extract a file within a folder within a zip?

I need to extract a file called Preview.pdf from a folder called QuickLooks inside of a zip file.
Right now my code looks a little like this:
with ZipFile(newName, 'r') as newName:
newName.extract(\QuickLooks\Preview.pdf)
newName.close()
(In this case, newName has been set equal to the full path to the zip).
It's important to note that the backslash is correct in this case because I'm on Windows.
The code doesn't work; here's the error it gives:
Traceback (most recent call last):
File "C:\Users\Asit\Documents\Evam\Python_Scripts\pageszip.py", line 18, in <module>
ZF.extract("""QuickLooks\Preview.pdf""")
File "C:\Python33\lib\zipfile.py", line 1019, in extract
member = self.getinfo(member)
File "C:\Python33\lib\zipfile.py", line 905, in getinfo
'There is no item named %r in the archive' % name)
KeyError: "There is no item named 'QuickLook/Preview.pdf' in the archive"
I'm running the Python script from inside Notepad++, and taking the output from its console.
How can I accomplish this?
Alternatively, how could I extract the whole QuickLooks folder, move out Preview.pdf, and then delete the folder and the rest of it's contents?
Just for context, here's the rest of the script. It's a script to get a PDF of a .pages file. I know there are bonified converters out there; I'm just doing this as an excercise with some sort of real-world application.
import os.path
import zipfile
from zipfile import *
import sys
file = raw_input('Enter the full path to the .pages file in question. Please note that file and directory names cannot contain any spaces.')
dir = os.path.abspath(os.path.join(file, os.pardir))
fileName, fileExtension = os.path.splitext(file)
if fileExtension == ".pages":
os.chdir(dir)
print (dir)
fileExtension = ".zip"
os.rename (file, fileName + ".zip")
newName = fileName + ".zip" #for debugging purposes
print (newName) #for debugging purposes
with ZipFile(newName, 'w') as ZF:
print("I'm about to list names!")
print(ZF.namelist()) #for debugging purposes
ZF.extract("QuickLook/Preview.pdf")
os.rename('Preview.pdf', fileName + '.pdf')
finalPDF = fileName + ".pdf"
print ("Check out the PDF! It's located at" + dir + finalPDF + ".")
else:
print ("Sorry, this is not a valid .pages file.")
sys.exit
I'm not sure if the import of Zipfile is redundant; I read on another SO post that it was better to use from zipfile import * than import zipfile. I wasn't sure, so I used both. =)
EDIT: I've changed the code to reflect the changes suggested by Blckknght.
Here's something that seems to work. There were several issues with your code. As I mentioned in a comment, the zipfile must be opened with mode 'r' in order to read it. Another is that zip archive member names always use forward slash / characters in their path names as separators (see section 4.4.17.1 of the PKZIP Application Note). It's important to be aware that there's no way to extract a nested archive member to a different subdirectory with Python's currentzipfilemodule. You can control the root directory, but nothing below it (i.e. any subfolders within the zip).
Lastly, since it's not necessary to rename the .pages file to .zip — the filename you passZipFile() can have any extension — I removed all that from the code. However, to overcome the limitation on extracting members to a different subdirectory, I had to add code to first extract the target member to a temporary directory, and then copy that to the final destination. Afterwards, of course, this temporary folder needs to deleted. So I'm not sure the net result is much simpler...
import os.path
import shutil
import sys
import tempfile
from zipfile import ZipFile
PREVIEW_PATH = 'QuickLooks/Preview.pdf' # archive member path
pages_file = input('Enter the path to the .pages file in question: ')
#pages_file = r'C:\Stack Overflow\extract_test.pages' # hardcode for testing
pages_file = os.path.abspath(pages_file)
filename, file_extension = os.path.splitext(pages_file)
if file_extension == ".pages":
tempdir = tempfile.gettempdir()
temp_filename = os.path.join(tempdir, PREVIEW_PATH)
with ZipFile(pages_file, 'r') as zipfile:
zipfile.extract(PREVIEW_PATH, tempdir)
if not os.path.isfile(temp_filename): # extract failure?
sys.exit('unable to extract {} from {}'.format(PREVIEW_PATH, pages_file))
final_PDF = filename + '.pdf'
shutil.copy2(temp_filename, final_PDF) # copy and rename extracted file
# delete the temporary subdirectory created (along with pdf file in it)
shutil.rmtree(os.path.join(tempdir, os.path.split(PREVIEW_PATH)[0]))
print('Check out the PDF! It\'s located at "{}".'.format(final_PDF))
#view_file(final_PDF) # see Bonus below
else:
sys.exit('Sorry, that isn\'t a .pages file.')
Bonus: If you'd like to actually view the final pdf file from the script, you can add the following function and use it on the final pdf created (assuming you have a PDF viewer application installed on your system):
import subprocess
def view_file(filepath):
subprocess.Popen(filepath, shell=True).wait()

Categories