Solved

How To Loop - Python

Posted on 2016-10-03
19
62 Views
Last Modified: 2016-10-07
Hello Experts -

I am familiar with looping in programming in general but I am a novice in python. I am trying to get my code to loop through a directory of MDBs and basically do compact and repair. I have the working code that does work for one file but I need it do it repeatedly for every file in the given directory.

The given directory would be a network path: \\fp1\rowp

import subprocess
import os

def mdb_repair(mdb_path, msaccess='C:/Program Files/Microsoft Office/Office15/msaccess.exe'):
    """Repairs the mdb_path database using the msaccess utility."""
    return subprocess.check_output([msaccess, '/compact', '/repair', mdb_path])

if __name__ == '__main__':    
    mdb_repair('C:\\Test\\AR001.mdb')

Open in new window

0
Comment
Question by:sj77
  • 7
  • 7
  • 3
  • +1
19 Comments
 
LVL 45

Expert Comment

by:aikimark
Comment Utility
os.listdir() will give you an iterable list of files in a directory.
0
 
LVL 45

Expert Comment

by:aikimark
Comment Utility
the glob library does facilitate filtering the list of files with a wildcard pattern.

reference: https://docs.python.org/2/library/glob.html
0
 
LVL 45

Expert Comment

by:aikimark
Comment Utility
The subprocess library has a check_output() function that may be more efficient if you have a lot of files in the folder and want the OS's file system to do the filtering.
0
 

Author Comment

by:sj77
Comment Utility
Logically though is where I am stuck. I am not a strong programmer, so, I would not know which loop condition to use and how to structure it. Some guidance would help...
0
 
LVL 45

Expert Comment

by:aikimark
Comment Utility
Please test this:
mdbs=subprocess.check_output("dir /b C:\Test\*.mdb",shell=True)
for m in mdbs.split("\r\n"):
    if len(m) <>0:
        mdb_repair('C:\\Test\\' + m)

Open in new window

0
 
LVL 1

Expert Comment

by:ltpitt
Comment Utility
What about this (needs testing):

import subprocess
import os

folder_path = "c:/your/mdb/path"

def mdb_repair(mdb_path, msaccess='C:/Program Files/Microsoft Office/Office15/msaccess.exe'):
    """Repairs the mdb_path database using the msaccess utility."""
    return subprocess.check_output([msaccess, '/compact', '/repair', mdb_path])


if __name__ == '__main__':
    for file in os.listdir(folder_path):
        filename, file_extension = os.path.splitext(file)
        if file_extension.lower() == '.mdb':
            mdb_repair(file)

Open in new window

0
 
LVL 28

Expert Comment

by:pepr
Comment Utility
Here is the code that calls the print instead of your function to show how to do it. I have tried the faked .mdb files. Notice that one of them has the .MDB extension (capital letters). Read the comments and see the output below the code:
#!python3

import glob
import os

print('------ glob')
# The glob.glob() is probably the easiest to use here. Notice that it
# finds also the files with the extension .MDB (that is capital letters).
lst = glob.glob('d:/__Python/sj77/ee28974050/*.mdb')
for fname in lst:
    print(fname)

print('------ bare name by listdir()')
# The os.listdir() return only the list of bare names.
lst = os.listdir('d:/__Python/sj77/ee28974050')
for fname in lst:
    print(fname)

# It is always good to assign things like a path to a variable.
# You may usually guess, but once you type it more than once, it should
# be clear. Moreover, later you may wrap the code as a function body,
# and the variable will become its argument (that is no need to rewrite
# the function body).
directory = 'd:/__Python/sj77/ee28974050'

print('------ listdir result joined with the directory')
# You can use the os.path.join() to join the directory with the bare name.
# However, notice that the earlier glob.glob() is probably easier to read.
lst = os.listdir(directory)
for fname in lst:
    print(os.path.join(directory, fname))

print('------ listdir result joined with the directory')
# If it is simple enough, no need for the extra variable (here lst).
for fname in os.listdir(directory):
    print(os.path.join(directory, fname))

print('------ normalized')
# Sometimes the extra variable is better to introduce (here fullname).
# In Windows, users are used to see backslashes instead of slashes.
# You can normalize the path (if you need some uniform output; anyway,
# it is better to use normal slashes in your code). Anyway, the name casing
# is not changed (here the .MDB with capital letters).
for fname in os.listdir(directory):
    fullname = os.path.normpath(os.path.join(directory, fname))
    print(fullname)

print('------ the alternative testing for the .mdb extension')
# As ltpitt has shown, splitting the extension is often used.
# Sometimes, it may be easier to read when you just test with .endswith()
# string methods. However, you still need to convert to .lower()
for fname in os.listdir(directory):
    fullname = os.path.normpath(os.path.join(directory, fname))
    if fullname.lower().endswith('.mdb'):
        print(fullname)

print('------ glob.iglob() as two lines')
# The glob.glob() returns the list of strings, and then the list is
# often iterated using the for loop. There is also the .iglob() variant
# that does not save the path to the list first. Instead, it returns
# the file names one by one. Notice, that you can still use the directory
# variable and the os.path.join() (or possibly even the .normpath() to build
# the mask for the glob. (The glob functionality and the name came from UNIX.)
for fname in glob.iglob(os.path.join(directory, '*.mdb')):
    print(fname)

# For me, the last one is the shortest, easiest to read, less error prone,
# and efficient (or with the full path, or with os.path.join() -- it depends
# on situation.
#
# Call your function instead of the print().

Open in new window

The output in my case was:
d:\__Python\sj77\ee28974050>py a.py
------ glob
d:/__Python/sj77/ee28974050\a.mdb
d:/__Python/sj77/ee28974050\b.mdb
d:/__Python/sj77/ee28974050\c.MDB
------ bare name by listdir()
a.mdb
a.py
b.mdb
c.MDB
------ listdir result joined with the directory
d:/__Python/sj77/ee28974050\a.mdb
d:/__Python/sj77/ee28974050\a.py
d:/__Python/sj77/ee28974050\b.mdb
d:/__Python/sj77/ee28974050\c.MDB
------ listdir result joined with the directory
d:/__Python/sj77/ee28974050\a.mdb
d:/__Python/sj77/ee28974050\a.py
d:/__Python/sj77/ee28974050\b.mdb
d:/__Python/sj77/ee28974050\c.MDB
------ normalized
d:\__Python\sj77\ee28974050\a.mdb
d:\__Python\sj77\ee28974050\a.py
d:\__Python\sj77\ee28974050\b.mdb
d:\__Python\sj77\ee28974050\c.MDB
------ the alternative testing for the .mdb extension
d:\__Python\sj77\ee28974050\a.mdb
d:\__Python\sj77\ee28974050\b.mdb
d:\__Python\sj77\ee28974050\c.MDB
------ glob.iglob() as two lines
d:/__Python/sj77/ee28974050\a.mdb
d:/__Python/sj77/ee28974050\b.mdb
d:/__Python/sj77/ee28974050\c.MDB

Open in new window

1
 

Author Comment

by:sj77
Comment Utility
Hi @Itpitt-

Thank you for that. It works but I get the below error.

Here is my code:
import subprocess
import os

folder_path = ('C:\\Test\\')

def mdb_repair(mdb_path, msaccess='C:/Program Files/Microsoft Office/Office15/msaccess.exe'):
    """Repairs the mdb_path database using the msaccess utility."""
    return subprocess.check_output([msaccess, '/compact', '/repair', mdb_path])


if __name__ == '__main__':
    for file in os.listdir(folder_path):
        filename, file_extension = os.path.splitext(file)
        if file_extension.lower() == '.mdb':
            mdb_repair(file)

Open in new window

error2python.jpg
0
 

Author Comment

by:sj77
Comment Utility
so @pepr what do you recommend I do?
0
Enabling OSINT in Activity Based Intelligence

Activity based intelligence (ABI) requires access to all available sources of data. Recorded Future allows analysts to observe structured data on the open, deep, and dark web.

 
LVL 1

Expert Comment

by:ltpitt
Comment Utility
My bad!

Add this row:

if __name__ == '__main__':
    os.cwd(folder_path)
    for file in os.listdir(folder_path):
        filename, file_extension = os.path.splitext(file)
        if file_extension.lower() == '.mdb':
            mdb_repair(file)
0
 

Author Comment

by:sj77
Comment Utility
@Itpitt -

Thank you!

I did and got the following error:

========= RESTART: C:\Users\imelendez\Desktop\python\CNR_AllFiles.py =========
Traceback (most recent call last):
  File "C:\Users\imelendez\Desktop\python\CNR_AllFiles.py", line 22, in <module>
    os.cwd(folder_path)
AttributeError: module 'os' has no attribute 'cwd'

Open in new window


current code:
import subprocess
import os

folder_path = ('C:\\Test\\')

def mdb_repair(mdb_path, msaccess='C:/Program Files/Microsoft Office/Office15/msaccess.exe'):
    """Repairs the mdb_path database using the msaccess utility."""
    return subprocess.check_output([msaccess, '/compact', '/repair', mdb_path])


if __name__ == '__main__':
    os.cwd(folder_path)
    for file in os.listdir(folder_path):
        filename, file_extension = os.path.splitext(file)
        if file_extension.lower() == '.mdb':
            mdb_repair(file)

Open in new window

0
 
LVL 45

Expert Comment

by:aikimark
Comment Utility
@Sj77

Have you tested my code?
0
 

Author Comment

by:sj77
Comment Utility
@aikimark

Yes, got invalid synthax error at <>0:

The highlighting was on the > sign.
0
 
LVL 45

Expert Comment

by:aikimark
Comment Utility
That feedback would have been helpful three days ago :-(
0
 
LVL 45

Expert Comment

by:aikimark
Comment Utility
Then try this inequality check syntax.
        if len(m)!=0:

Open in new window

both run fine in Python 2.7
1
 

Author Comment

by:sj77
Comment Utility
My apologies. I thought I had replied and clearly I did not. I am using v 3.5.2
0
 
LVL 28

Accepted Solution

by:
pepr earned 500 total points
Comment Utility
I suggest to write another tiny function for repairing all .mdb files in the directory that is passed as its argument. Try this, and then uncomment the ##result = subprocess... line and the ##return line:
#!python3

import glob
import os
import subprocess

def mdb_repair(mdb_path, msaccess='C:/Program Files/Microsoft Office/Office15/msaccess.exe'):
    """Repairs the mdb_path database using the msaccess utility."""
    mdb_path = os.path.normpath(mdb_path)   # let's make the print more tidy
    print('Repairing', mdb_path, '...', end=' ')
    ##result = subprocess.check_output([msaccess, '/compact', '/repair', mdb_path])
    print('done')
    ##return result

    
def repair_all_mdbs_in_folder(folder_path):
   """Finds all .mdb files in the folder_path and calls the repair function for them."""
   for fname in glob.iglob(os.path.join(folder_path, '*.mdb')):
       mdb_repair(fname)
       # Possibly also capture and process the output of the function if you need.
    

if __name__ == '__main__':
    repair_all_mdbs_in_folder('c:/Test/')

Open in new window

1
 
LVL 1

Expert Comment

by:ltpitt
Comment Utility
Hi again...

I completed a few versions with slightly different use scenario.

This one is the 1st one I've sent you, now with bug fixed:
import subprocess
import os

folder_path = ('C:\\Test\\')

def mdb_repair(mdb_path, msaccess='C:/Program Files/Microsoft Office/Office15/msaccess.exe'):
    """Repairs the mdb_path database using the msaccess utility."""
    return subprocess.check_output([msaccess, '/compact', '/repair', mdb_path])


if __name__ == '__main__':
    os.chdir(folder_path)
    for file in os.listdir(folder_path):
        filename, file_extension = os.path.splitext(file)
        if file_extension.lower() == '.mdb':
            mdb_repair(file)

Open in new window



This other one takes, as input from user, the path you that the user wants to fix.
Basically when the script is running, the user will be prompted to use the keyboard to input the path.

# Importing used libraries to handle files / folders / etc
import subprocess
import os

# This function is used to get the mdb path as input from user
def get_path_from_user():
# Prints an empty row to show what the script is doing with more clarity
    print()
# Asks the user which is the path and saves it in input_path variable
    input_path = raw_input("Please enter your path (example: c:/my/folder/): ")
# Checks if path written from user exists
    if os.path.exists(input_path):
# If path exists switches folder to the path folder
        os.chdir(input_path)
# For every file available in the folder
        for file in os.listdir(folder_path):
# Divide file name from file extension
            filename, file_extension = os.path.splitext(file)
# If file extension is ".mdb"
            if file_extension.lower() == '.mdb':
# Call function mdb_repair on that file
                mdb_repair(file)
    else:
# Since path could not be found let's print an error to the user
        print "\n*** Folder does not exist! ***"

def mdb_repair(mdb_path, msaccess='C:/Program Files/Microsoft Office/Office15/msaccess.exe'):
    """Repairs the mdb_path database using the msaccess utility."""
    print "Repairing files..."
    return subprocess.check_output([msaccess, '/compact', '/repair', mdb_path])

if __name__ == '__main__':
    get_path_from_user()

Open in new window



The last version is maybe more flexible because it allows you to specify the path as a parameter when running the script from command line.

Example:
python your_script_name.py c:/your/mdb/folder/

Here you can find it:
# Importing used libraries to handle files / folders / etc
import subprocess
import os
import sys

# This function is used to get the mdb path as input from user
def check_if_path_exists(input_path):
    print sys.argv[1]
# Prints an empty row to show what the script is doing with more clarity
    print()
# Checks if path written from user exists
    if os.path.exists(input_path):
# If path exists switches folder to the path folder
        os.chdir(input_path)
# For every file available in the folder
        for file in os.listdir(folder_path):
# Divide file name from file extension
            filename, file_extension = os.path.splitext(file)
# If file extension is ".mdb"
            if file_extension.lower() == '.mdb':
# Call function mdb_repair on that file
                mdb_repair(file)
    else:
# Since path could not be found let's print an error to the user
        print "\n*** Folder does not exist! ***"

def mdb_repair(mdb_path, msaccess='C:/Program Files/Microsoft Office/Office15/msaccess.exe'):
    """Repairs the mdb_path database using the msaccess utility."""
    print "Repairing files..."
    return subprocess.check_output([msaccess, '/compact', '/repair', mdb_path])

if __name__ == '__main__':
# Verify if user specified a path when the script was run
    if len(sys.argv) > 1:
# If so put this data into the variable input_path
        input_path = sys.argv[1]
# And run the get_path_from_user function
        check_if_path_exists(input_path)
    else:
        print "\n*** Please specify a path! ***"

Open in new window

1
 

Author Closing Comment

by:sj77
Comment Utility
WOW, again, @pepr you do not fail!

Thank you, this worked!
0

Featured Post

Better Security Awareness With Threat Intelligence

See how one of the leading financial services organizations uses Recorded Future as part of a holistic threat intelligence program to promote security awareness and proactively and efficiently identify threats.

Join & Write a Comment

There is an easy way, in .NET, to centralize the treatment of all unexpected errors. First of all, instead of launching the application directly in a Form, you need first to write a Sub called Main, in a module. Then, set the Startup Object to th…
Article by: Swadhin
Introduction of Lists in Python: There are six built-in types of sequences. Lists and tuples are the most common one. In this article we will see how to use Lists in python and how we can utilize it while doing our own program. In general we can al…
The goal of this video is to provide viewers with basic examples to understand and use conditional statements in the C programming language.
The viewer will be introduced to the member functions push_back and pop_back of the vector class. The video will teach the difference between the two as well as how to use each one along with its functionality.

763 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

6 Experts available now in Live!

Get 1:1 Help Now