Solved

How To Loop - Python

Posted on 2016-10-03
Medium Priority
114 Views
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')

0
Question by:sj77
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

• Help others & share knowledge
• Earn cash & points
• 7
• 7
• 3
• +1

LVL 46

Expert Comment

ID: 41827178
os.listdir() will give you an iterable list of files in a directory.
0

LVL 46

Expert Comment

ID: 41827180
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 46

Expert Comment

ID: 41827186
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

ID: 41827189
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 46

Expert Comment

ID: 41827210
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)

0

LVL 1

Expert Comment

ID: 41827587

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)

0

LVL 29

Expert Comment

ID: 41828837
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.
#

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

1

Author Comment

ID: 41832175
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)

error2python.jpg
0

Author Comment

ID: 41832181
so @pepr what do you recommend I do?
0

LVL 1

Expert Comment

ID: 41832255

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

ID: 41832340
@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'


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)

0

LVL 46

Expert Comment

ID: 41832429
@Sj77

Have you tested my code?
0

Author Comment

ID: 41832480
@aikimark

Yes, got invalid synthax error at <>0:

The highlighting was on the > sign.
0

LVL 46

Expert Comment

ID: 41832504
That feedback would have been helpful three days ago :-(
0

LVL 46

Expert Comment

ID: 41832510
Then try this inequality check syntax.
        if len(m)!=0:

both run fine in Python 2.7
1

Author Comment

ID: 41832611
My apologies. I thought I had replied and clearly I did not. I am using v 3.5.2
0

LVL 29

Accepted Solution

pepr earned 2000 total points
ID: 41832682
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/')

1

LVL 1

Expert Comment

ID: 41833158
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)


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
# 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()


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! ***"

1

Author Closing Comment

ID: 41834187
WOW, again, @pepr you do not fail!

Thank you, this worked!
0

Featured Post

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Dictionaries contain key:value pairs. Which means a collection of tuples with an attribute name and an assigned value to it. The semicolon present in between each key and values and attribute with values are delimited with a comma.  In python we can…
Windows Script Host (WSH) has been part of Windows since Windows NT4. Windows Script Host provides architecture for building dynamic scripts that consist of a core object model, scripting hosts, and scripting engines. The key components of Window…
This tutorial explains how to use the VisualVM tool for the Java platform application. This video goes into detail on the Threads, Sampler, and Profiler tabs.
This video will show you how to get GIT to work in Eclipse.   It will walk you through how to install the EGit plugin in eclipse and how to checkout an existing repository.
Suggested Courses
Course of the Month15 days, 11 hours left to enroll