Access an .sde connection file using UNC path instead of the local "Database Connections"

5049
6
Jump to solution
07-29-2015 06:40 PM
RebeccaStrauch__GISP
MVP Emeritus

I'm working in 10.2.2 (and 10.3.1...and testing in Pro).  I'm trying to use a standard set of "connection files" for .sde, .and ags, connection files so running the scripts  will work on multiple machines. However, I'm trying to keep it generic enough in case someone else uses with a different (local) connection file type.  This is a program that is pretty specific to our needs, but is run often (currently only by me, but that will change).

Typically these connection files are stored in a path similar to

C:\Users\<user>\AppData\Roaming\ESRI\Desktop10.x\ArcCatalog

I would like to store them in a shared network folder with the UNC pathname, e.g.

\\<server>\GISStaff\myConnection@database.sde

The problem:

It seems that if I use the connection file, the arcpy.CopyFeatures_management (and probably any other command) it wants:

Database Connections\myConnection@database.sde\master.DBO.theMasters\thePolys

If I use the UNC connection file, the command wants (note "master.DBO" in bold near end):

\\newserver\GISStaff\myConnection@database.sde\master.DBO.theMasters\master.DBO.thePolys

Question:

Other than checking for the string "Database Connections" in my variable, does anyone know a way to check whether the .sde file is in the local connection folder vs. a UNC path?  If I can test for it reliably, I can strip the data I need and add it to the string before I add the featureclass name.  (I'll be able to handle that)

Interesting (?) side note: in previous ArcGIS versions (maybe 9.x or 10.0), I always had to have the additional info in the path. Then in one of the updates to ArcGIS, that broken the script and I had take it back to just the featureclass name.....seems this is a combination or maybe a remnant of the old way.  (??)

I'm trying to keep it simple, but flexible, without having to hard code the path.

This is arcpy/python specific, but cross posting since GDB/SDE related  Geodatabase

Thanks for any suggestions!

EDIT:  it may be that I will just do the test for the "database Connection' string like this:

if 'Database Connection' in masterGDB2:
  <leave as is>
else:
  <add the database.owner>

So in that case, can anyone tell me how to strip everything before and including   ".sde\\' from before my database.owner?

Message was edited by: Rebecca Strauch Revised, in case no easy test....then would just need "strip" syntax help.

1 Solution

Accepted Solutions
XanderBakker
Esri Esteemed Contributor

And to include the missing part:

import os

def main():
    unc_path = r"\\newserver\GISStaff\myConnection@database.sde\master.DBO.theMasters\thePolys"
    normal_path = r"C:\Users\blahblah\AppData\Roaming\ESRI\Desktop10.x\ArcCatalog\myConnection@database.sde\master.DBO.theMasters\thePolys"
    db_path = r"Database Connections\myConnection@database.sde\master.DBO.theMasters\thePolys"

    lst = [unc_path, normal_path, db_path]
    for p in lst:
        if isuncpath(p):
            lst = os.path.split(p)
            print os.path.join(lst[0], 'master.DBO.{0}'.format(lst[1]))
        else:
            print p

def isuncpath(a_path):
    return os.path.splitunc(a_path)[0] != ''

if __name__ == '__main__':
    main()

which will yield:

\\newserver\GISStaff\myConnection@database.sde\master.DBO.theMasters\master.DBO.thePolys
C:\Users\blahblah\AppData\Roaming\ESRI\Desktop10.x\ArcCatalog\myConnection@database.sde\master.DBO.theMasters\thePolys
Database Connections\myConnection@database.sde\master.DBO.theMasters\thePolys

View solution in original post

0 Kudos
6 Replies
XanderBakker
Esri Esteemed Contributor

In Python there is not much support for UNC paths (as to check for them or to define credentials to connect to them). You could use something like this:

def main():
    unc_path = r"\\newserver\GISStaff\myConnection@database.sde"
    normal_path = r"C:\Users\blahblah\AppData\Roaming\ESRI\Desktop10.x\ArcCatalog\myConnection@database.sde"
    db_path = r"Database Connections\myConnection@database.sde"

    lst = [unc_path, normal_path, db_path]
    for p in lst:
        print isuncpath(p), p

def isuncpath(a_path):
    import os
    return os.path.splitunc(a_path)[0] != ''

if __name__ == '__main__':
    main()

... which will return this:

True \\newserver\GISStaff\myConnection@database.sde
False C:\Users\blahblah\AppData\Roaming\ESRI\Desktop10.x\ArcCatalog\myConnection@database.sde
False Database Connections\myConnection@database.sde
0 Kudos
XanderBakker
Esri Esteemed Contributor

And to include the missing part:

import os

def main():
    unc_path = r"\\newserver\GISStaff\myConnection@database.sde\master.DBO.theMasters\thePolys"
    normal_path = r"C:\Users\blahblah\AppData\Roaming\ESRI\Desktop10.x\ArcCatalog\myConnection@database.sde\master.DBO.theMasters\thePolys"
    db_path = r"Database Connections\myConnection@database.sde\master.DBO.theMasters\thePolys"

    lst = [unc_path, normal_path, db_path]
    for p in lst:
        if isuncpath(p):
            lst = os.path.split(p)
            print os.path.join(lst[0], 'master.DBO.{0}'.format(lst[1]))
        else:
            print p

def isuncpath(a_path):
    return os.path.splitunc(a_path)[0] != ''

if __name__ == '__main__':
    main()

which will yield:

\\newserver\GISStaff\myConnection@database.sde\master.DBO.theMasters\master.DBO.thePolys
C:\Users\blahblah\AppData\Roaming\ESRI\Desktop10.x\ArcCatalog\myConnection@database.sde\master.DBO.theMasters\thePolys
Database Connections\myConnection@database.sde\master.DBO.theMasters\thePolys
0 Kudos
RebeccaStrauch__GISP
MVP Emeritus

Hi Xander,

Between the isuncpath and the lst = os.path.split(p)   I'm getting really close.  But I can't hard code the  "master.DBO" since that will change.

In my case, lst[1]    is actually      'sde_wcgis_master.DBO.DWCMasters'

What is the correct syntax to end up with   just the   'sde_wcgis_master.DBO.'   portion (since the  lst[1] could change).    I'm assuming it is a flavor of strip, I just haven't found the right combo yet.  (still testing though)

EDIT:  getting my last question figured out.  I was trying to use strip instead of split

zz = lst[1].split('.')

I can work with that.

Thanks for your help Xander.  I think I'm ready to roll in the morning on this!

0 Kudos
RebeccaStrauch__GISP
MVP Emeritus

I'm adding this summary for anyone that might need to do a similar thing.  I'm using Xander Bakker 'isuncpath' function to check whether it is a local (mapped) drive or a UNC path. Then based on the results, I'm building the sdePath variable as need to get the path that arcpy needs for input to the CopyFeatures command (and most likely others).

If within your target geodatabase you are trying to write to a feature dataset vs the root of the database, look at how I'm assigning the targetFC variable (commented out since I'm not providing the other variables in this sample)

The sample below doesn't do anything but print out the sdePath and the paths for the FCs in the For loop.  To test with the different types of local vs UNC paths, switch (un-comment) the other masterGDB attribute assignment line.

import arcpy
import os
# function to see if the masterGDB path is UNC or "local"
def isuncpath(a_path):  
    return os.path.splitunc(a_path)[0] != ''

def main():
    
    #set path to one of the below
    masterGDB = r'Database Connections\me@master.sde\myDatabase.DBO.Masters'
    #masterGDB = r'\\newserver\Staff\___gisStaffConnections\me@master.sde\myDatabase.DBO.DWCMasters'

    if isuncpath(masterGDB):  
        lstSdeFDS = os.path.split(masterGDB)   
        lstDbOwnerFDS = lstSdeFDS[1].split(".")
        sdePath =  ('{0}\\{1}.{2}.'.format(masterGDB, lstDbOwnerFDS[0], lstDbOwnerFDS[1]))
        print('sdePath: {0}'.format(sdePath))
    else:  
        sdePath = masterGDB + "\\"
        print('sdePath: {0}'.format(sdePath))

    #then for using in my comands    
    for fdsToCopy  in ['Fclass1', 'FClass2', 'FClass3']:
        #print('       Copying Master database {0} to temporary Master_update FGDB: ... '.format(fdsToCopy) )
        sourceFC = sdePath + fdsToCopy
        print('sourceFC path: {0}'.format(sourceFC))
        # next two lines are commented out since I'm not showing the setting of 
        #    the updateFGDN and MasterFDS variables...but showing so others can get the gist
        #targetFC = updateFGDB + '\\' + masterFDS + '\\' + fdsToCopy
        #arcpy.CopyFeatures_management (sourceFC, targetFC)

# End main function

if __name__ == '__main__':
    main()
XanderBakker
Esri Esteemed Contributor

To get back to your question to exclude the last part of a string separated by points, you could do this:

s = 'sde_wcgis_master.DBO.DWCMasters'

# split the string on the point and exclude the last element and join it with pionts
print '.'.join(s.split('.')[:-1])

# then I noticed the rpartition that splits on the last occurrence (first from right), take the first part.
print s.rpartition('.')[0]

# to include to point at the end
print '{0}.'.format('.'.join(s.split('.')[:-1]))
print '{0}.'.format(s.rpartition('.')[0])

# or shorter, just add the point
print '.'.join(s.split('.')[:-1]) + '.'
print s.rpartition('.')[0] + '.'
RebeccaStrauch__GISP
MVP Emeritus

Thanks Xander.  Those are all slick. I may try to merge those into my script at some point (but working, so moved on to next script) but it is definitely good reference for next time.  I appreciate the additional options.  I'm still trying to get in the habit of cleaner looking code....still do a lot of brunt force with python (but getting better).