AttributeError: __len__ Error with ntpath.py an Tkinter.py - python

I get the following error when I run a script and it's changing the directory - how can I bug fix this?
Traceback (most recent call last): File
"L:\Data_Admin\QA\Metadata_python_toolset\test2\update_Metadata1e.py",
line 17, in
currentPath=os.path.join(root,directory) File "C:\Python26\ArcGIS10.0\lib\ntpath.py", line 96, in join
assert len(path) > 0 File "C:\Python26\ArcGIS10.0\lib\lib-tk\Tkinter.py", line 1722, in
getattr
return getattr(self.tk, attr) AttributeError: len
Full code
import os, xml, arcpy, shutil, datetime, Tkinter,tkFileDialog
from xml.etree import ElementTree as et
path=os.getcwd()
RootDirectory=path
arcpy.env.workspace = path
Count=0
Generated_XMLs=RootDirectory+'\GeneratedXML_LOG.txt'
f = open(Generated_XMLs, 'a')
f.write("Log of Metadata Creation Process - Update: "+str(datetime.datetime.now())+"\n")
f.close()
for root, dirs, files in os.walk(RootDirectory, topdown=False):
#print root, dirs
for directory in dirs:
currentPath=os.path.join(root,directory)
os.chdir(currentPath)
arcpy.env.workspace = currentPath
print currentPath
#def Create_xml(currentPath):
FileList = arcpy.ListFeatureClasses()
zone="_Zone"
for File in FileList:
Count+=1
FileDesc_obj = arcpy.Describe(File)
FileNm=FileDesc_obj.file
check_meta=os.listdir(currentPath)
existingXML=FileNm[:FileNm.find('.')]
existingExtension=FileNm[FileNm.find('.'):]
print "XML: "+existingXML
#print check_meta
#if existingXML+'.xml' in check_meta:
#newMetaFile='new'
for f in check_meta:
if f.startswith(existingXML) and f.endswith('.xml'):
print "exists, file name:", f
newMetaFile=FileNm+"_2012Metadata.xml"
shutil.copy2(f, newMetaFile)
break
else:
#print "Does not exist"
newMetaFile=FileNm+"_BaseMetadata.xml"
print "New meta file: "+newMetaFile+ " for: "+File
if newMetaFile.endswith('_BaseMetadata.xml'):
print "calling tkinter"
root = Tkinter.Tk()
file = tkFileDialog.askopenfile(parent=root,mode='rb',title='Choose a xml base file to match with: '+File)
if file != None:
metafile=os.path.abspath(file.name)
file.close()
#print metafile
shutil.copy2(metafile,newMetaFile)
print "copied"+metafile
root.destroy
else:
shutil.copy2('L:\Data_Admin\QA\Metadata_python_toolset\Master_Metadata.xml', newMetaFile)
print "Parsing meta file: "+newMetaFile
tree=et.parse(newMetaFile)
print "Processing: "+str(File)
for node in tree.findall('.//title'):
node.text = str(FileNm)
for node in tree.findall('.//northbc'):
node.text = str(FileDesc_obj.extent.YMax)
for node in tree.findall('.//southbc'):
node.text = str(FileDesc_obj.extent.YMin)
for node in tree.findall('.//westbc'):
node.text = str(FileDesc_obj.extent.XMin)
for node in tree.findall('.//eastbc'):
node.text = str(FileDesc_obj.extent.XMax)
for node in tree.findall('.//native/nondig/formname'):
node.text = str(os.getcwd()+"\\"+File)
for node in tree.findall('.//native/digform/formname'):
node.text = str(FileDesc_obj.featureType)
for node in tree.findall('.//avlform/nondig/formname'):
node.text = str(FileDesc_obj.extension)
for node in tree.findall('.//avlform/digform/formname'):
node.text = str(float(os.path.getsize(File))/int(1024))+" KB"
for node in tree.findall('.//theme'):
node.text = str(FileDesc_obj.spatialReference.name +" ; EPSG: "+str(FileDesc_obj.spatialReference.factoryCode))
print node.text
projection_info=[]
Zone=FileDesc_obj.spatialReference.name
if "GCS" in str(FileDesc_obj.spatialReference.name):
projection_info=[FileDesc_obj.spatialReference.GCSName, FileDesc_obj.spatialReference.angularUnitName, FileDesc_obj.spatialReference.datumName, FileDesc_obj.spatialReference.spheroidName]
print "Geographic Coordinate system"
else:
projection_info=[FileDesc_obj.spatialReference.datumName, FileDesc_obj.spatialReference.spheroidName, FileDesc_obj.spatialReference.angularUnitName, Zone[Zone.rfind(zone)-3:]]
print "Projected Coordinate system"
x=0
for node in tree.findall('.//spdom'):
for node2 in node.findall('.//keyword'):
print node2.text
node2.text = str(projection_info[x])
print node2.text
x=x+1
tree.write(newMetaFile)
f = open(Generated_XMLs, 'a')
f.write(str(Count)+": "+File+"; "+newMetaFile+"; "+currentPath+"\n")
f.close()
print "change dir 1"
print "change dir 2"
# Create_xml(currentPath)

It's possible that your os.chdir is confusing os.walk. Try restoring the working directory before the next iteration.
Better yet, you can use a with statement if you define a context manager for chdir. Here's an example, which defines a version of chdir that you can use as follows:
for root, dirs, files in os.walk(RootDirectory, topdown=False):
for directory in dirs:
currentPath=os.path.join(root,directory)
with chdir(currentPath):
# now inside the specified directory
# after exiting 'with', original directory will be restored

Related

Python rename file based on file in same directory

I have a file directory structure like this:
/folder
aaa.pdf
bbb.xml
stamped.pdf
Where PDF and XML file names have no patterns to them, except that every folder has stamped.pdf in it (stamped.pdf needs to be ignored).
I want to rename the .xml file in the directory to match the .pdf file name, so I end up with:
/folder
aaa.pdf
aaa.xml
stamped.pdf
Python so far (not renaming anything yet, just trying to get the filenames at this point)
import os
pdf = ('.pdf')
xml = ('.xml')
stamped = ('stamped.pdf')
for folderName, subfolders, filenames in os.walk('folder'):
print('The current folder is ' + folderName)
for filename in filenames:
namefile = os.path.splitext(filename)[0]
if (filename.endswith(pdf) and filename != stamped):
pdfname = namefile
print('PDF File Name: ' + pdfname)
if filename.endswith(xml):
print('RENAME XML FILE NAME: ' + namefile + 'TO: ' pdfname)
else:
print('')
print('')
Right now I'm just printing values before I get into the renaming.
In the script above, pdfname is undefined in the XML conditional, because the pdfname variable isn't set/available in the XML conditional.
How can I pass the pdfname variable so that it can be used to rename the XML file in the same directory?
Thanks!
import os
for parent, _, files in os.walk('.'):
if not files:
continue
pdf_file = None
xml_file = None
for filename in files:
if filename.lower().endswith('.pdf') and filename.lower() != 'stamped.pdf':
pdf_file = filename
elif filename.lower().endswith('.xml'):
xml_file = filename
new_xml_filename = '{}/{}.xml'.format(parent, os.path.splitext(pdf_file)[0])
xml_file = '{}/{}'.format(parent, xml_file)
if os.path.exists(new_xml_filename):
print('cannot rename %s without overwriting an existing file. skipping' % xml_file)
continue
else:
os.rename(xml_file, new_xml_filename)
print('renamed {} -> {}'.format(xml_file, new_xml_filename))

traverse directory structure in python recursively without os.walk

I am trying to write a python2 function that will recursively traverse through the whole directory structure of a given directory, and print out the results.
All without using os.walk
This is what I have got so far:
test_path = "/home/user/Developer/test"
def scanning(sPath):
output = os.path.join(sPath, 'output')
if os.path.exists(output):
with open(output) as file1:
for line in file1:
if line.startswith('Final value:'):
print line
else:
for name in os.listdir(sPath):
path = os.path.join(sPath, name)
if os.path.isdir(path):
print "'", name, "'"
print_directory_contents(path)
scanning(test_path)
This is what I currently get, the script doesn't enter the new folder:
' test2'
'new_folder'
The issue is that it does not go further down than one directory. I would also like to able to indicate visually what is a directory, and what is a file
Try this:
import os
test_path = "YOUR_DIRECTORY"
def print_directory_contents(dir_path):
for child in os.listdir(dir_path):
path = os.path.join(dir_path, child)
if os.path.isdir(path):
print("FOLDER: " + "\t" + path)
print_directory_contents(path)
else:
print("FILE: " + "\t" + path)
print_directory_contents(test_path)
I worked on windows, verify if still working on unix.
Adapted from:
http://codegists.com/snippet/python/print_directory_contentspy_skobnikoff_python
Try this out with recursion
it is much simple and less code
import os
def getFiles(path="/var/log", files=[]):
if os.path.isfile(path):
return files.append(path)
for item in os.listdir(path):
item = os.path.join(path, item)
if os.path.isfile(item):
files.append(item)
else:
files = getFiles(item, files)
return files
for f in getFiles("/home/afouda/test", []):
print(f)
Try using a recursive function,
def lastline(fil):
with open(fil) as f:
for li in f.readlines():
if li.startswith("Final Value:"):
print(li)
## If it still doesnt work try putting 'dirs=[]' here
def lookforfiles(basepath):
contents = os.listdir(basepath)
dirs = []
i = 0
while i <= len(contents):
i += 1
for n in contents:
f = os.path.join(basepath, n)
if os.path.isfile(f):
lastline(f)
print("\n\nfile %s" % n)
elif os.path.isdir(f):
print("Adding dir")
if f in dirs:
pass
else:
dirs.append(f)
else:
for x in dirs:
print("dir %s" % x)
lookforfiles(x)
sorry if this doesn't fit your example precisely but I had a hard time understanding what you were trying to do.
This question is a duplicate of Print out the whole directory tree.
TL;TR: Use os.listdir.

Python bulk renamer works, but doesn't work at the same time?

when I run the program from the command line I get no errors and it seems to execute, but nothing happens! I'm ready to stab my eyes out from staring at code for so long. I just want this to work so I can turn it in and be done with this assignment.
The program is supposed to run as follows.
python bulk.py (directory name) (name for files)
import os
import sys
import random
def filterByExtension(root, allfiles, extensions):
matching = []
ext = []
for i in allfiles:
name = i
dot = name.rfind('.')
ext = name[dot+1:].lower()
if ext not in extensions:
continue
path = os.path.join(root, name)
if not os.path.isfile(path):
print "Warning: File type not expected"
continue
if os.path.isfile(path):
matching.append(name)
return matching
def sortByMTime(path, matching):
presort = []
for file in matching:
path = os.path.join(path, file)
mtime = os.path.getmtime(path)
presort.append((mtime, file))
presort.sort()
return presort
print "Here is the presorted shtuff",presort
def assignNames(prefix, inorder):
count = ''
digits = 0
count = str(len(inorder))
digits = len(count)
template = '%%0%dd' % digits
newnames = {}
count = 0
for i in inorder:
count += 1
s = template % count
newnames[i[1]] = prefix+s+'.'+i[1].split('.')[1]
return newnames
print "Here are the new names that will be used",newnames
def makeTempName(allfiles):
n = random.randint(1, 1000000000)
t = '__temp' + str(n) + '__'
while t in allfiles:
n += 1
t = '__temp' + str(n) + '__'
return t
def makeScript(inorder, newnames, tempname):
script = []
print
print "a"
print
for elt in inorder:
print
print "b"
print
chain = []
inthechain = {}
if elt not in newnames:
continue
if newnames[elt] == elt:
del newnames[elt]
continue
if newnames[elt] not in newnames:
print "This is the script output inside the if statement:"
print script
script.append( (elt,newnames[elt]) )
del newnames[elt]
continue
else:
link = elt
while True:
target = newnames[elt]
chain.append( (link,target) )
inthechain[link] = True
link = target
if link not in newnames:
break
chain.reverse()
print "this is the chain output before loop:"
print chain
for ( a, b ) in chain:
print "This is the output of chain:"
print chain
script.append( a, b )
del newnames[a]
print 'here is the inthechain output in function'
print inthechain
print '=========================================='
print 'here is the inorder output in function'
print inorder
print '=========================================='
print 'here is the newnames output in function'
print newnames
print '=========================================='
print 'here is the tempname output in function'
print tempname
print '=========================================='
print 'here is the script output in function'
print script
print '=========================================='
return script
def doRenames(pathfull, script):
for entry in script:
print entry[0], '->', entry[1]
oldpath = os.path.join(path, entry[0])
newpath = os.path.join(path, entry[1])
if os.path.exists(newpath):
print 'Error: file name already exists.'
os.exit(1)
else:
os.rename(oldpath, newpath)
def main():
directory = []
prefix = []
path = []
tempname = []
if len(sys.argv) <= 1 or len(sys.argv) > 3:
print "You have messed up, please check your arguments again"
sys.exit(1)
elif len(sys.argv) == 3:
directory = sys.argv[1]
path = os.path.abspath(directory)
dirname = os.path.basename(path)
print "Directory: ", sys.argv[1:-1]
print "Prefix: ", sys.argv[-1]
allfiles = []
allfiles = os.listdir(sys.argv[1])
print allfiles
extensions = []
extensions = ['jpeg','jpg','png','gif']
matching = filterByExtension(path, allfiles, extensions)
inorder = sortByMTime(path, matching)
newnames = assignNames(prefix, inorder)
tempname = makeTempName(allfiles)
script = makeScript(inorder, newnames, tempname)
renamed = doRenames(path, script)
else:
directory = sys.argv[1]
path = os.path.abspath(directory)
dirname = os.path.basename(path)
print "Directory: ", path
print "Prefix: ", dirname
main()
No file names will ever be added to matching here:
if not os.path.isfile(path):
print "Warning: File type not expected"
continue
if os.path.isfile(path):
matching.append(name)
Probably you wanted to have the second if in the outer block, not indented under the first if:
if not os.path.isfile(path):
print "Warning: File type not expected"
continue
if os.path.isfile(path):
matching.append(name)
Or, simpler:
if not os.path.isfile(path):
print "Warning: File type not expected"
else:
matching.append(name)

Code being dropped from xml created using python

I am copying and then updating a metadata xml file using python -this works fine except that the following code from the original metafile is being deleted
<?xml version="1.0" encoding="utf-8"?><?xml-stylesheet type='text/xsl' href='ANZMeta.xsl'?>
It needs to go at the start of the file.
The answer for this in PHP is # xml insertion at specific point of xml file but I need a solution for Python.
The code and full explanation is in my original post but I am seperating this question as it is different from the original issues I had. Search and replace multiple lines in xml/text files using python
Thanks,
FULL CODE
import os, xml, arcpy, shutil, datetime, Tkinter, tkFileDialog, tkSimpleDialog
from xml.etree import ElementTree as et
path=os.getcwd()
RootDirectory=path
currentPath=path
arcpy.env.workspace = path
Count=0
DECLARATION = """<?xml version="1.0" encoding="utf-8"?>
<?xml-stylesheet type='text/xsl' href='ANZMeta.xsl'?>\n"""
Generated_XMLs=RootDirectory+'\GeneratedXML_LOG.txt'
f = open(Generated_XMLs, 'a')
f.write("Log of Metadata Creation Process - Update: "+str(datetime.datetime.now())+"\n")
f.close()
for root, dirs, files in os.walk(RootDirectory, topdown=False):
#print root, dirs
for directory in dirs:
try:
currentPath=os.path.join(root,directory)
except:
pass
os.chdir(currentPath)
arcpy.env.workspace = currentPath
print currentPath
#def Create_xml(currentPath):
FileList = arcpy.ListFeatureClasses()
zone="_Zone"
for File in FileList:
Count+=1
FileDesc_obj = arcpy.Describe(File)
FileNm=FileDesc_obj.file
check_meta=os.listdir(currentPath)
existingXML=FileNm[:FileNm.find('.')]
existingExtension=FileNm[FileNm.find('.'):]
print "XML: "+existingXML
#print check_meta
#if existingXML+'.xml' in check_meta:
#newMetaFile='new'
for f in check_meta:
if f.startswith(existingXML) and f.endswith('.xml'):
print "exists, file name:", f
newMetaFile=FileNm+"_2012Metadata.xml"
try:
shutil.copy2(f, newMetaFile)
except:
pass
break
else:
#print "Does not exist"
newMetaFile=FileNm+"_BaseMetadata.xml"
print "New meta file: "+newMetaFile+ " for: "+File
if newMetaFile.endswith('_BaseMetadata.xml'):
print "calling tkinter"
root = Tkinter.Tk()
root.withdraw()
file = tkFileDialog.askopenfile(parent=root,mode='rb',title='Choose a xml base file to match with: '+File)
if file != None:
metafile=os.path.abspath(file.name)
file.close()
#print metafile
shutil.copy2(metafile,newMetaFile)
print "copied"+metafile
root.destroy
else:
shutil.copy2('L:\Data_Admin\QA\Metadata_python_toolset\Master_Metadata.xml', newMetaFile)
#root = Tkinter.Tk()
#root.withdraw()
#newTitle=tkSimpleDialog.askstring('title', 'prompt')
#root.destroy
#print newTitle
print "Parsing meta file: "+newMetaFile
tree=et.parse(newMetaFile)
print "Processing: "+str(File)
for node in tree.findall('.//title'):
node.text = str(FileNm)
for node in tree.findall('.//procstep/srcused'):
node.text = str(currentPath+"\\"+existingXML+".xml")
dt=dt=str(datetime.datetime.now())
for node in tree.findall('.//procstep/date'):
node.text = str(dt[:10])
for node in tree.findall('.//procstep/time'):
node.text = str(dt[11:13]+dt[16:19])
for node in tree.findall('.//metd/date'):
node.text = str(dt[:10])
for node in tree.findall('.//northbc'):
node.text = str(FileDesc_obj.extent.YMax)
for node in tree.findall('.//southbc'):
node.text = str(FileDesc_obj.extent.YMin)
for node in tree.findall('.//westbc'):
node.text = str(FileDesc_obj.extent.XMin)
for node in tree.findall('.//eastbc'):
node.text = str(FileDesc_obj.extent.XMax)
for node in tree.findall('.//native/nondig/formname'):
node.text = str(os.getcwd()+"\\"+File)
for node in tree.findall('.//native/digform/formname'):
node.text = str(FileDesc_obj.featureType)
for node in tree.findall('.//avlform/nondig/formname'):
node.text = str(FileDesc_obj.extension)
for node in tree.findall('.//avlform/digform/formname'):
node.text = str(float(os.path.getsize(File))/int(1024))+" KB"
for node in tree.findall('.//theme'):
node.text = str(FileDesc_obj.spatialReference.name +" ; EPSG: "+str(FileDesc_obj.spatialReference.factoryCode))
print node.text
projection_info=[]
Zone=FileDesc_obj.spatialReference.name
if "GCS" in str(FileDesc_obj.spatialReference.name):
projection_info=[FileDesc_obj.spatialReference.GCSName, FileDesc_obj.spatialReference.angularUnitName, FileDesc_obj.spatialReference.datumName, FileDesc_obj.spatialReference.spheroidName]
print "Geographic Coordinate system"
else:
projection_info=[FileDesc_obj.spatialReference.datumName, FileDesc_obj.spatialReference.spheroidName, FileDesc_obj.spatialReference.angularUnitName, Zone[Zone.rfind(zone)-3:]]
print "Projected Coordinate system"
x=0
for node in tree.findall('.//spdom'):
for node2 in node.findall('.//keyword'):
#print node2.text
node2.text = str(projection_info[x])
#print node2.text
x=x+1
tree.write(newMetaFile)
with open(newMetaFile, 'w') as output: # would be better to write to temp file and rename
output.write(DECLARATION)
tree.write(output, xml_declaration=False, encoding='utf-8')
# xml_declaration=False - don't write default declaration
f = open(Generated_XMLs, 'a')
f.write(str(Count)+": "+File+"; "+newMetaFile+"; "+currentPath+";"+existingXML+"\n")
f.close()
# Create_xml(currentPath)
Error message from Wing IDE
xml.parsers.expat.ExpatError: no element found: line 3, column 0 File
"L:\Data_Admin\QA\Metadata_python_toolset\test2\update_Metadata1f.py",
line 78, in tree=et.parse(newMetaFile) File
"C:\Python26\ArcGIS10.0\Lib\xml\etree\ElementTree.py", line 862, in
parse tree.parse(source, parser) File
"C:\Python26\ArcGIS10.0\Lib\xml\etree\ElementTree.py", line 587, in
parse self._root = parser.close() File
"C:\Python26\ArcGIS10.0\Lib\xml\etree\ElementTree.py", line 1254, in
close self._parser.Parse("", 1) # end of data
I struggled with adding PI's to the start of an ElementTree document too. I came up with a solution using a fake root node (with None as the element tag) to hold any required processing instructions and then the real document root node.
import xml.etree.ElementTree as ET
# Build your XML document as normal...
root = ET.Element('root')
# Create 'fake' root node
fake_root = ET.Element(None)
# Add desired processing instructions. Repeat as necessary.
pi = ET.PI("xml-stylesheet", "type='text/xsl' href='ANZMeta.xsl'")
pi.tail = "\n"
fake_root.append(pi)
# Add real root as last child of fake root
fake_root.append(root)
# Write to file, using ElementTree.write( ) to generate <?xml ...?> tag.
tree = ET.ElementTree(fake_root)
tree.write("doc.xml", xml_declaration=True)
The resulting doc.xml file:
<?xml version='1.0' encoding='us-ascii'?>
<?xml-stylesheet type='text/xsl' href='ANZMeta.xsl'?>
<root />
If all your xml files have the same declaration, you can write it by yourself:
import xml.etree.ElementTree as ET
DECLARATION = """<?xml version="1.0" encoding="utf-8"?>
<?xml-stylesheet type='text/xsl' href='ANZMeta.xsl'?>\n"""
tree = ET.parse(filename)
# do some work on tree
with open(filename, 'w') as output: # would be better to write to temp file and rename
output.write(DECLARATION)
tree.write(output, xml_declaration=False, encoding='utf-8')
# xml_declaration=False - don't write default declaration

Backup Script in Python

can some one please provide me with an explanation of the code especially the use of maxversions and statements following the line "for f in files:".
I want to understand what xrange(MAXVERSION) means? What is the use of indexing i.e
for index in xrange(MAXVERSIONS): backup = '%s.%2.2d' % (destpath, index)
The code:
!/usr/bin/env python
import sys,os, shutil, filecmp
MAXVERSIONS=100
BAKFOLDER = '.bak'
def backup_files(tree_top, bakdir_name=BAKFOLDER):
top_dir = os.path.basename(tree_top)
tree_top += os.sep
for dir, subdirs, files in os.walk(tree_top):
if os.path.isabs(bakdir_name):
relpath = dir.replace(tree_top,'')
backup_dir = os.path.join(bakdir_name, top_dir, relpath)
else:
backup_dir = os.path.join(dir, bakdir_name)
if not os.path.exists(backup_dir):
os.makedirs(backup_dir)
subdirs[:] = [d for d in subdirs if d != bakdir_name]
for f in files:
filepath = os.path.join(dir, f)
destpath = os.path.join(backup_dir, f)
for index in xrange(MAXVERSIONS):
backup = '%s.%2.2d' % (destpath, index)
abspath = os.path.abspath(filepath)
if index > 0:
old_backup = '%s.%2.2d' % (destpath, index-1)
if not os.path.exists(old_backup): break
abspath = os.path.abspath(old_backup)
try:
if os.path.isfile(abspath) and filecmp.cmp(abspath, filepath, shallow=False):
continue
except OSError:
pass
try:
if not os.path.exists(backup):
print 'Copying %s to %s...' % (filepath, backup)
shutil.copy(filepath, backup)
except (OSError, IOError), e:
pass
if __name__=="__main__":
if len(sys.argv)<2:
sys.exit("Usage: %s [directory] [backup directory]" % sys.argv[0])
tree_top = os.path.abspath(os.path.expanduser(os.path.expandvars(sys.argv[1])))
if len(sys.argv)>=3:
bakfolder = os.path.abspath(os.path.expanduser(os.path.expandvars(sys.argv[2])))
else:
bakfolder = BAKFOLDER
if os.path.isdir(tree_top):
backup_files(tree_top, bakfolder)
The script tries to recursively copy the contents of a directory (defaults to current directory) to a backup directory (defaults to .bak in the current directory);
for each filename.ext, it creates a duplicate named filename.ext.00; if filename.ext.00 already exists, it creates filename.ext.01 instead, and so on.
xrange() is a generator which returns all numbers in 0..(MAXVERSION-1), so MAXVERSION controls how many version-suffixes to try, ie how many old versions of the file to keep.

Categories

Resources