mardi 22 août 2017

Can I Replace Part of a Python "If" Statement with a Variablized String Literal?

I have a very long question with what may be a very short answer.

I'm very new to Python (almost two weeks, now) but I've used VBScript for many years so I understand many of the basic concepts.

I've searched Stack Overflow and the internet for a solution but haven't been able to find anything; I'm not sure if this is even possible in Python, but I'd be a bit surprised if it's not. I've written a file-search program using Python3 that allows users to search their computer for files. The user can choose to search based on several different parameters: name, size range, date-modified range and, for non-Linux systems, date-created range. The search functionaly works quite well for each individual parameter as well as for combinations of parameters (which, by the way, is in no small part thanks to the many answers / discussions I've found here on Stack Overflow). My problem is that the actual search is rather inelegant and, I believe, slower than it could be. The program uses flags (NOT true Python flags, that's just what I happen to call them) to set the search options. Let me illustrate with some pseudo code:

    # Variables get their values from user entry
    sName = "test" # string to search for
    sMinSize = 2 # minimum search-by size in MB
    sMaxSize = 15 # maximum search-by size in MB
    sModded1 = 2008-01-23 # earliest modified-by date
    sModded2 = 2017-08-22 # latest modified-by date

    sCreated1 = 2008-01-23 # earliest created-by date
    sCreated2 = 2017-08-22 # latest created-by date

    # Search parameters - choosing one of these changes the value from 0 to 1:
    flagName = 0 # search by name
    flagSize = 0 # search by size
    flagModified = 0 # search by last modified date
    flagCreated = 0 # search by last created date

    for root, dirs, files in os.walk(strPath, followlinks=False):
        for fName in files:
            fileDate = os.path.getmtime(fName)
            fileSize = os.stat(fName).st_size
            if flagName = 1:
                    if fName.find(sName) > 0:
                        do_stuff
            elif flagSize = 1:        
                    if sMinSize < fileSize < sMaxSize:
                        do_stuff
            elif flagName = 1 and flagSize = 1:
                    if fName.find(sName) > 0 and if sMinSize < fileSize < sMaxSize:
                        do_stuff
    ... etc

That's only for 3 possible combinations - there are 14 total. While I don't really have a problem with typing all the combinations out, I believe this would severely impact the speed and efficiency of the search.

I've thought of another solution that is a bit more elegant and would probably execute faster, but I still think there's a better method:

    if flagName = 1:
        for root, dirs, files in os.walk(strPath, followlinks=False):
            for fName in files:
                fileDate = os.path.getmtime(fName)
                fileSize = os.stat(fName).st_size
                if fName.find(sName) > 0:
                    do_stuff

    elif flagName = 1 and flagSize = 1:
        for root, dirs, files in os.walk(strPath, followlinks=False):
            for fName in files:
                fileDate = os.path.getmtime(fName)
                fileSize = os.stat(fName).st_size
                if fName.find(sName) > 0 and if sMinSize < fileSize < sMaxSize:
                    do_stuff
    ... etc

Again, this is a bit more elegant and (I believe) a great deal more efficient, but still not ideal. What I'd like to do is create ONE "if" statement based on the user's search criteria and use that to conduct the search (note that something similar is possible in VBScript). These statements would go BEFORE the search statements take place:

Possible option 1:

    if flagName = 1:
        iClause = "fName.find(sName) > 0"
    elif flagName = 1 and flagSize = 1:
        iClause = "fName.find(sName) > 0 and if sMinSize < fileSize < sMaxSize"
    ... etc

Possible option 2:

    flagClause = 0
    if flagName = 1:
        iClause = "fName.find(sName) > 0"
        flagClause = flagClause + 1
    if flagClause = 0
        iClause = "sMinSize < fileSize < sMaxSize"
    else:
        iClause = iClause + "and sMinSize < fileSize < sMaxSize"
        flagClause = flagClause + 1
    ... etc

And then plug "iClause" in to my search statement like so:

    for root, dirs, files in os.walk(strPath, followlinks=False):
        for fName in files:
            fileDate = os.path.getmtime(fName)
            fileSize = os.stat(fName).st_size
            if **iClause**:
                do_stuff

This would streamline the code, making it easier to read and maintain and (I believe) make it more efficient and speedy.

Is this possible with Python?

Aucun commentaire:

Enregistrer un commentaire