I'm trying to save all layers in my ArcMap mxd as .lyr files using the script below. However, I'm getting an error because some group layer names contain special characters (e.g. © : * ) and cannot be written into folder names.
How can I make sure special characters are ignored/replaced?
import os
basepath = r'C:\Users\Anneka\Dropbox (The Rivers Trust)\CaBA_Data_Phase5\Layers'
mxd = arcpy.mapping.MapDocument("CURRENT")
for lyr in arcpy.mapping.ListLayers(mxd):
if lyr.isGroupLayer == True:
grpPath = os.path.join(basepath, str(lyr))
if not os.path.exists(grpPath):
os.makedirs(grpPath)
else:
fn = os.path.join(basepath, str(lyr) + ".lyr")
lyr.saveACopy(fn)
The error:
Runtime error
Traceback (most recent call last):
File "<string>", line 10, in <module>
File "C:\Python27\ArcGIS10.6\Lib\os.py", line 157, in makedirs
mkdir(name, mode)
WindowsError: [Error 123] The filename, directory name, or volume label syntax is incorrect: 'C:\\Users\\Anneka\\Dropbox (The Rivers Trust)\\CaBA_Data_Phase5\\Layers\\Issues\\Rivers\\WFD Classification Sites 2016 (EA)*'
2 Answers 2
You can use non-ascii characters in file/folder names. However, you can't use reserved characters or words in file/folder names.
If you are getting a UnicodeEncodeError: 'ascii' codec can't encode character etc...
exception, you are trying to encode unicode to ascii when your script uses str(lyr)
(not when you try to create a file/folder). Instead of doing that, just use the lyr
objects longName
property which is a unicode string. You can then just save your file as is.
You'll see something like ValueError: Layer: Unexpected error
if your layer names contains reserved characters/words.
The reserved characters are:
- < (less than)
- > (greater than)
- : (colon)
- " (double quote)
- / (forward slash)
- \ (backslash)
- | (vertical bar or pipe)
- ? (question mark)
- * (asterisk)
The reserved words are CON, PRN, AUX, NUL, COM1, COM2, COM3, COM4, COM5, COM6, COM7, COM8, COM9, LPT1, LPT2, LPT3, LPT4, LPT5, LPT6, LPT7, LPT8, and LPT9
You could handle both the UnicodeEncodeError
and ValueError
using something like:
import os
import arcpy
def fix_name(name):
replace = '_'
reserved_chars = [u'<', u'>', u':', u'"', u'/', u'|', u'?', u'*'] # u'\\' is reserved, but we use as directory separator
reserved_words = [u'CON', u'PRN', u'AUX', u'NUL',
u'COM1', u'COM2', u'COM3', u'COM4', u'COM5', u'COM6', u'COM7', u'COM8', u'COM9',
u'LPT1', u'LPT2', u'LPT3', u'LPT4', u'LPT5', u'LPT6', u'LPT7', u'LPT8', u'LPT9']
for char in reserved_chars:
name = name.replace(char, replace)
name = os.sep.join([replace + b + replace if b.upper() in reserved_words else b for b in name.split(os.sep)])
return name
basepath = r'C:\Temp'
mxd = arcpy.mapping.MapDocument(r"C:\Temp\Test.mxd") # "("CURRENT")
for lyr in arcpy.mapping.ListLayers(mxd):
name = fix_name(lyr.longName)
if lyr.isGroupLayer:
grpPath = os.path.join(basepath, name)
if not os.path.exists(grpPath):
os.makedirs(grpPath)
else:
fn = os.path.join(basepath, name + ".lyr")
lyr.saveACopy(fn)
print("Saved: " + fn)
So for this:
The output is:
Saved: C:\Temp\Überwald\Group Layer\_NUL_.lyr
Saved: C:\Temp\Überwald\Group Layer\_LPT2_.lyr
Saved: C:\Temp\Überwald\Group Layer\Überwald Sub_Group Layer\Überwald Coastline.lyr
Saved: C:\Temp\Überwald\Group Layer\Überwald Sub_Group Layer\Überwald Base Map.lyr
Saved: C:\Temp\Temperature (°C).lyr
Saved: C:\Temp\A_B_.lyr
-
This almost worked! But it would seem that the issue is that some group names have special characters, and windows doesn't allow special characters in folder names (even though it does in individual file names)Anneka– Anneka2019年05月01日 09:44:44 +00:00Commented May 1, 2019 at 9:44
-
@Anneka I have just tested with special characters in folder names and it works fine. What doesn't work is trying to use reserved characters as specified in docs.microsoft.com/en-us/windows/desktop/fileio/…user2856– user28562019年05月02日 01:55:03 +00:00Commented May 2, 2019 at 1:55
This is untested but, from reviewing Remove all special characters, punctuation and spaces from string at Stack Overflow, I think it should work:
import os
basepath = r'C:\Users\Anneka\CaBA_Data_Phase_5\Layers'
mxd = arcpy.mapping.MapDocument("CURRENT")
for lyr in arcpy.mapping.ListLayers(mxd):
if lyr.isGroupLayer == True:
grpPath = os.path.join(basepath, str(lyr))
if not os.path.exists(grpPath):
os.makedirs(grpPath)
else:
newLayerName = ''.join(e for e in str(lyr) if e.isalnum())
fn = os.path.join(basepath, newLayerName + ".lyr")
lyr.saveACopy(fn)
print "Saved: " + fn
Explore related questions
See similar questions with these tags.