|
POST
|
And to do the actual renaming, try something like os.rename(os.path.join(root,fname), os.path.join(root,newname))
... View more
04-16-2019
11:47 AM
|
0
|
5
|
6002
|
|
POST
|
Here's a snippet that shows some options: jpg = 'file.jpg'
fn = jpg.split('.')[0] # first part of jpg name by splitting on dot
print fn
# file
exif = '2018:06:05 13:49:40' # date/time from exif data
exifdt = exif.replace(':','-').replace(' ','_') # replace colons and space
print exifdt
# 2018-06-05_13-49-40
newname = fn+"_"+exifdt+".jpg"
print newname
# file_2018-06-05_13-49-40.jpg You could split the exif data on the space to remove the time. However, including time may be useful in preventing duplicate file names. Also, I like dates in the year-month-day format as it helps sorting, but that is a personal preference. Hope this helps.
... View more
04-16-2019
10:52 AM
|
1
|
0
|
6002
|
|
POST
|
You should delete line 9 in your last code sample, and then adjust the variable name in line 10. Try something like: for root, dirnames, filenames in os.walk(im):
for fname in filenames:
if fname.endswith('.JPG'):
with open(os.path.join(root, fname), 'rb') as image: #file path and name
exif = exifread.process_file(image)
dt = str(exif['EXIF DateTimeOriginal'])#get JPG 'Date taken'
ds = time.strptime(dt, '%Y:%m:%d %H:%M:%S')
print(time.strftime("%m/%d/%Y",ds)) Also, I try to avoid using variable names like date and time as they sometimes can conflict with items in the include modules (instead I use dt for datetime and ds for datestring, for example).
... View more
04-12-2019
09:29 AM
|
1
|
0
|
4060
|
|
POST
|
Try: st = '2018:06:05 13:49:40'
dt = time.strptime(st, '%Y:%m:%d %H:%M:%S')
print time.strftime("%m/%d/%Y",dt) I was experimenting with some exif code in my answers in this thread which may be of interest.
... View more
04-11-2019
02:30 PM
|
1
|
2
|
4060
|
|
POST
|
When I wanted a count of domain values used in all fields in a feature, I used the following. It ignores 'Range' type domains, but it might give you some ideas. To limit it to a specific field, you could use something like: field.name == 'field_name'. import arcpy
gdb = r"C:\path\to\file.gdb"
arcpy.env.workspace = gdb # set environment for arcpy
fc = 'feature_name' # a feature in the geodatabase
# gdb domains to dictionary # # # # # # #
domDict = {} # empty dictionary
domains = arcpy.da.ListDomains(gdb)
for domain in domains:
if domain.domainType == 'CodedValue':
if domain.name not in domDict:
vList = [] # empty list
coded_values = domain.codedValues
for val, desc in coded_values.items():
vList.append({val:desc})
domDict[domain.name] = vList
# print domDict
# read feature's fields and domains information # # # # # # #
fields = arcpy.ListFields(fc)
fldDict = {} # empty dictionary
for field in fields:
if len(field.domain):
fldDict[field.name] = field.domain
# print fldDict
# count values in fields with domains # # # # # # #
domCount = {}
fldList = list(fldDict.keys())
with arcpy.da.SearchCursor(fc, fldList) as rows:
for row in rows:
for i, f in enumerate(fldList):
# print i, fldList, row # index, field name, field value
if fldList not in domCount:
domCount[fldList] = {}
if row not in domCount[fldList]:
domCount[fldList][row] = 1
else:
domCount[fldList][row] += 1
del rows # release any locks
# print domCount
# output the results # # # # # # #
for k, v in domCount.iteritems():
print "Field: {}".format(k)
print " Domain: {}".format(fldDict )
for dLst in domDict[fldDict ]:
for k1, v1 in dLst.iteritems():
if k1 in v:
print " Key: {} - Description: {} - Count: {}".format(k1, v1, v[k1])
else:
print " Key: {} - Description: {} - Count: {}".format(k1, v1, 0)
# note, this does not check for invalid codes in domain fields
An example of the output for one field: Field: Observed
Domain: YN
Key: Y - Description: Yes - Count: 159
Key: ? - Description: ? - Count: 121
Key: N - Description: No - Count: 255
... View more
04-11-2019
02:12 PM
|
2
|
0
|
13217
|
|
POST
|
A timestamp would be like: fset = FL.query(where = 'CreationDate > TIMESTAMP 1551355736000' )
... View more
04-03-2019
04:27 PM
|
0
|
2
|
10356
|
|
POST
|
It has been a while since my experimenting. I'll try to dig up my code. What you can do is explore the REST API on AGOL and examine the returned html and json. This should give you an idea of the coding needed and the process to follow. The link to a feature should look something like: https://<services>.arcgis.com/<account>/arcgis/rest/services/<feature>/FeatureServer/<layerID>?token=<token> The link to query attachments (I've used "OBJECTID > 0' for the definition expression: https://<services>.arcgis.com/<account>/arcgis/rest/services/<feature>/FeatureServer/<layerID>/queryAttachments?token=<token> The links to update and add attachments will return a multi-part form: https://<services>.arcgis.com/<account>/arcgis/rest/services/<feature>/FeatureServer/<layerID>/<parentID>/updateAttachment?token=<token>
https://<services>.arcgis.com/<account>/arcgis/rest/services/<feature>/FeatureServer/<layerID>/<parentID>/addAttachment?token=<token>
... View more
03-26-2019
09:55 AM
|
0
|
1
|
1298
|
|
POST
|
I've updated some attachments, so you should be able to move them. Start by checking: Query Attachments. There are links on the side of the page for Add Attachments and Delete Attachments.
... View more
03-23-2019
06:46 PM
|
0
|
1
|
1298
|
|
POST
|
I believe there are some data entry issues with the some of the rows in Weld 1. I have made some code adjustments in the answer above. You should replace the while block and the update cursor block. One of the errors appears to be a circular reference. I believe that rows 1138 and 1139 should go between 328 and 329. I suspect an error with the values 533 and 533A. Since these values follow the 1:1 rule of matching up:down values, neither value was identified as the start and stop of a line segment. Therefore, it was causing a KeyError in the update cursor. OID UP DOWN LINE SEGMENT
330 543 540 1029 37
329 540 533 1029 38
1138 533A 536A (circular reference)
1139 536A 533A
328 533 519 1029 39
327 519 527 1029 40
The second error is a bit more puzzling. The points are in proximity, but I am not sure how they are connected. Does the down T-3 connect to row 1158 or 1144. Numerically, 1144 makes sense, but with the 1:1 rule, T3 should only be in the up column once. And there are two single points that are not connected unless I1220F connects to 1220F. OID UP DOWN LINE SEGMENT
1142 1216E L-11 IJ-2 2
1143 L-11 T-3 IJ-2 3
1156 I1220F YL-1 I1220F 1
1157 FL-11 1220F FL-11 1
1158 T-3 FL-2 IJ-2 4
1144 T-3 1216B ERROR -1
1145 1216B FL13 1216B 1 I would assume the errors are data entry errors. The code adjustments should help identify some of them.
... View more
03-23-2019
05:16 PM
|
0
|
1
|
1209
|
|
POST
|
While it is good to know something about field mappings, they can be annoying to work with. And there are alternatives. Here's some code I was testing that might be of interest. It starts by making a copy of the first dbf file. Then lines 14-21 checks for the specific field of interest, and if found, creates an identical type in the dbf copy. After creating the field, the script loads the second dbf's data of interest into a dictionary. An update cursor uses the dictionary to populate the newly created field. Note this is assuming there is a 1:1 match on the LABEL field. As script was just a quick test, some additional error checking may be necessary. import arcpy
import sys
# make a copy of the first dbf file
dbfAAA = r"C:\test\dbf\AAA.dbf" # this is the first dbf
dbfOUT = r"C:\test\dbf\OUT.dbf" # this is the copy fields will be added to
arcpy.Copy_management(dbfAAA, dbfOUT)
# this is the dbf containing the field we want
dbfBBB = r"C:\test\dbf\BBB.dbf"
fldsBBB = ['LABEL', 'BBB'] # fields for our dictionary, the second one is the one we need to copy
# get the field's information and add the same type of field to our copy dbf file
for field in arcpy.ListFields(dbfBBB,fldsBBB[1]):
if field.name is not None: # add field, (assuming all these properties are available)
arcpy.AddField_management(dbfOUT, field.name, field.type, field.precision,
field.scale, field.length, field.aliasName,
field.isNullable, field.required, field.domain)
else:
print "ERROR: field {} not found".format(fldsBBB[1])
sys.exit(0) # exit on error, may want to recode for more graceful exit
# read second dbf file into a dictionary
dicBBB = {r[0]:r[1] for r in arcpy.da.SearchCursor(dbfBBB, fldsBBB)}
# use update cursor to add the data to the dbf copy
with arcpy.da.UpdateCursor(dbfOUT,fldsBBB) as cursor:
for row in cursor:
row[1] = dicBBB[row[0]]
cursor.updateRow(row) Regarding field mappings, here is an old article from ArcUser that might be helpful: Use Field Mapping and Python Scripting to Make Your Job Easier PDF version
... View more
03-21-2019
10:15 PM
|
1
|
2
|
1088
|
|
POST
|
And in the Label Expression dialog, you need to use the \r\n pair for a new line with Python. It is one of the few places in Desktop where \n alone won't work as expected.
... View more
03-21-2019
11:09 AM
|
0
|
1
|
4451
|
|
POST
|
Thumbs.db is a hidden Windows file/folder. Windows likes to index photos and create icons, so it will have a reference to your jpegs . So between lines 9 and 10 in my sample code above, a test would need to be added to make sure that Thumbs.db is being excluded. I haven't tested it, but perhaps this would work for line 9: if file.endswith(".jpg") and 'Thumbs.db' not in root:
... View more
03-21-2019
10:28 AM
|
1
|
1
|
690
|
|
POST
|
I suspect the issue might be with the <0.50 value in the Carbon_tet field. You may have to escape the less-than symbol because you are using the "html-like" CLR tag. A greater-than symbol would also need escaping.
... View more
03-21-2019
10:13 AM
|
1
|
1
|
4451
|
|
POST
|
If you are using ListLayers, you might want to take another look at the documentation. From your question in a related thread, it appeared that you might only be referencing the active data frame. ListLayers requires a map document reference and an optional reference to the data frame. Hope this helps. ListLayers (map_document_or_layer, {wildcard}, {data_frame})
... View more
03-20-2019
12:38 PM
|
1
|
1
|
3172
|
|
POST
|
I was testing something like: import arcpy
import os
startDir = r'C:\path\to\jpegs\root'
jpgs = {} # empty dictionary
for root, dirs, files in os.walk(startDir):
for file in files:
if file.endswith(".jpg"): # for key, trim '.jpg'
jpgs[file[:-4]] = os.path.join(root,file)
# print jpgs
fc = r'C:\path\to\file.gdb\photos'
fields = ['OID@', 'Post_Number', 'Photo']
with arcpy.da.UpdateCursor(fc, fields) as cursor:
for row in cursor:
try:
row[2] = jpgs[row[1]]
cursor.updateRow(row)
except KeyError:
print "No photo for: {}".format(row[1])
del cursor This assumes the 'Post_Number' is text, and that the 'Photo' field length is able to take the complete path. I was testing with 2.7, so some adjustment may be needed for 3.x. I'm also not sure at what size a dictionary might become too big.
... View more
03-19-2019
09:39 PM
|
1
|
3
|
3344
|
| Title | Kudos | Posted |
|---|---|---|
| 1 | 10-27-2016 02:23 PM | |
| 1 | 09-09-2017 08:27 PM | |
| 2 | 08-20-2020 06:15 PM | |
| 1 | 10-21-2021 09:15 PM | |
| 1 | 07-19-2018 12:33 PM |
| Online Status |
Offline
|
| Date Last Visited |
02-12-2026
07:13 PM
|