I recently had the need to convert a local path to a UNC path for an application I was writing. The application monitors a local folder for files and serves them to a client over the network as requested, but for the client to be able to access the file the path had to be a UNC path.

There didn’t seem to be a built in way to do this in Python so here’s what I ended up with.

When the NetworkPaths class is initialised it will build a dictionary of available Windows shares on the current machine with the path as the key and share name as the value. It then creates a list of the share paths ordered by longest first.

When the convert method is given a path it works through the list of stored share paths checking to see if any match the start of the given path. If a match is found it builds the UNC path using the dictionary lookup to get the share name.

class NetworkPaths(object):
    def __init__(self):
        super(NetworkPaths, self).__init__()
        obj_wmi_service = win32com.client.Dispatch('WbemScripting.SWbemLocator')
        obj_s_wbem_services = obj_wmi_service.ConnectServer('.', 'root\cimv2')
        items = obj_s_wbem_services.ExecQuery('SELECT * FROM Win32_Share')
        self.shares_lookup = {str(share.Path): str(share.Name) for share in items if
                              share.Path and not '$' in share.Name and
                              not share.Name == 'Users'}
        self.shares = sorted((x for x in self.shares_lookup.keys()), key=len, reverse=True)

    def convert(self, local_path):
        if local_path[:2] == '\\\\':
            # Path is already UNC.
            return local_path
        for share_path in self.shares:
            if local_path.lower().startswith(share_path.lower()):
                # We have a match. Return the UNC path.
                if local_path[len(share_path)] == '\\':
                    path_end = local_path[len(share_path) + 1:]
                else:
                    path_end = local_path[len(share_path):]

                unc_path = os.path.join('\\\\{0:s}'.format(os.getenv('COMPUTERNAME')),
                                        self.shares_lookup[share_path],
                                        path_end)
                return unc_path
        # No match found.
        return None

For example, given the path C:\Users\Gary Hughes\Desktop\Batch Files\Full Backup.bat on my machine:

network_paths = NetworkPaths()
print network_paths.convert(r'C:\Users\Gary Hughes\Desktop\Batch Files\Full Backup.bat')

returns:

\\IRUSH\Desktop\Batch Files\Full Backup.bat

With the paths sorted by longest first this should ensure the shortest UNC path is returned.


Comments

comments powered by Disqus