Taliesin R Salomonson
Taliesin R Salomonson

Reputation: 15

Python: Use local variable globally does not work

I am trying to use my code to open a file after searching for it in either operating system. However when I assign the variable inside the function, i cant use it outside of the function. And when I keep the 2nd function out of 1st function, it doesnt recognize the function.

I tried to assign the df_location globally, but this doesnt work. When i use df = pd.read_csv(df_location[0], index_col=0) inside the function, I am not able to use df anywhere else in my code.

if platform.system() == 'windows':
    def find_file(root_folder, rex):
        for root, dirs, files in os.walk(root_folder):
            for f in files:
                result = rex.search(f)
                if result:
                    file_path = os.path.join(root, f)
                    return file_path  

    def find_file_in_all_drives(file_name):

        matching_files = list()
        # create a regular expression for the file
        rex = re.compile(file_name)
        for drive in win32api.GetLogicalDriveStrings().split('\000')[:-1]:
            file_path = find_file(drive, rex)
            if file_path:
                matching_files.append(file_path)
        return matching_files

    global df_location
    df_location = find_file_in_all_drives("AB_NYC_2019.csv")

if platform.system() == 'mac':
    df_location = find_file("/", "AB_NYC_2019.csv")


df = pd.read_csv(df_location[0], index_col=0)

I would like to be able to use the file that is retrieved through the functions.

Thank you!

ideally it should be like this

if platform.system() == 'windows':
    def find_file(root_folder, rex):
        for root, dirs, files in os.walk(root_folder):
            for f in files:
                result = rex.search(f)
                if result:
                    file_path = os.path.join(root, f)
        return file_path  

    def find_file_in_all_drives(file_name):

        matching_files = list()
        # create a regular expression for the file
        rex = re.compile(file_name)
        for drive in win32api.GetLogicalDriveStrings().split('\000')[:-1]:
            file_path = find_file(drive, rex)
            if file_path:
                matching_files.append(file_path)
        return matching_files

df_location = find_file_in_all_drives("AB_NYC_2019.csv")

if platform.system() == 'mac':
    df_location = find_file("/", "AB_NYC_2019.csv")


df = pd.read_csv(df_location[0], index_col=0)

but this gives the error message: "NameError: name 'find_file_in_all_drives' is not defined"

Upvotes: 0

Views: 140

Answers (2)

Paul M.
Paul M.

Reputation: 10809

You didn't show all your code. Presumably, you have find_file and find_file_in_all_drives function implementations for mac as well, yes? At least that's what I would expect just from looking at the code you've posted.

If that really is ALL the code you have, then the way it's written now, you're only defining find_file and find_file_in_all_drives if platform.system() returns "windows" (side note: just tried this, on my Windows 7 system it returns "Windows" with a capital 'W'.) If that condition is not satisfied these function definitions are not visible anywhere else in your code, because you've put them inside the body of the if-statement.

It looks like you are trying to get different behavior depending on the contents of a string (platform.system()). Since you can't avoid having to implement the varying behavior for both operating systems, you can use polymorphism for this:

import abc


class DataFrameFinder(abc.ABC):

    def __init__(self):
        pass

    @abc.abstractmethod
    def find_file(self, root_folder, rex):
        raise NotImplementedError

    @abc.abstractmethod
    def find_file_in_all_drives(self, file_name):
        raise NotImplementedError


class DataFrameFinderWindows(DataFrameFinder):

    def __init__(self, *args, **kwargs):
        DataFrameFinder.__init__(self, *args, **kwargs)

    def find_file(self, root_folder, rex):
        # Do windows things...
        pass

    def find_file_in_all_drives(self, file_name):
        # Do windows things...
        pass


class DataFrameFinderMac(DataFrameFinder):

    def __init__(self, *args, **kwargs):
        DataFrameFinder.__init__(self, *args, **kwargs)

    def find_file(self, root_folder, rex):
        # Do mac things...
        pass

    def find_file_in_all_drives(self, file_name):
        # Do mac things...
        pass

def main():

    import platform

    finder_factory = {
        "Windows": DataFrameFinderWindows,
        "Mac": DataFrameFinderMac
    }

    finder = finder_factory[platform.system()]()

    finder.find_file(...)

    return 0


if __name__ == "__main__":
    import sys
    sys.exit(main())

Upvotes: 1

furas
furas

Reputation: 142794

You define find_file_in_all_drives for Window but you should define find_file_in_all_drives also for other systems - but every system will have different code in find_file_in_all_drives. And then you can use find_file_in_all_drives on every system

# all systems use it so it should be defined for all

def find_file(root_folder, rex):
    for root, dirs, files in os.walk(root_folder):
        for f in files:
            result = rex.search(f)
            if result:
                file_path = os.path.join(root, f)
    return file_path  

# define different `find_file_in_all_drives` for different systems     

if platform.system() == 'windows':

    def find_file_in_all_drives(file_name):
        matching_files = list()
        # create a regular expression for the file
        rex = re.compile(file_name)
        for drive in win32api.GetLogicalDriveStrings().split('\000')[:-1]:
            file_path = find_file(drive, rex)
            if file_path:
                matching_files.append(file_path)
        return matching_files

if platform.system() in ('mac', 'linux'):

    def find_file_in_all_drives(file_name):
        return find_file("/", file_name)

# now you can use `find_file_in_all_drives` on every system

df_location = find_file_in_all_drives("AB_NYC_2019.csv")

df = pd.read_csv(df_location[0], index_col=0)

Upvotes: 1

Related Questions