Isaiah Melendez
asked on
Windows Command Line in Python
Hello Experts!
I am new to python so please excuse my naive nature.
I know that with python 3.5 you can call upon the subprocess class to execute windows command line and ultimately execute actions.
I want to do the following:
An example: like if you click run > cmd.exe > navigate to c:\test > run a bat file in there or if there is an application in there where I can run command line switches like test.exe \silent
Let me know if you need any further clarification.
Thank you all for your contribution in advance.
-Isaiah
I am new to python so please excuse my naive nature.
I know that with python 3.5 you can call upon the subprocess class to execute windows command line and ultimately execute actions.
I want to do the following:
- Be able to open up cmd.exe
- Be able to then navigate to a directory of my choice
- Execute a command once at that destination
An example: like if you click run > cmd.exe > navigate to c:\test > run a bat file in there or if there is an application in there where I can run command line switches like test.exe \silent
Let me know if you need any further clarification.
Thank you all for your contribution in advance.
-Isaiah
Can you describe better a bigger picture of what you really want to do. Can you create some.bat that does something and to describe what the Python program should do? Should the user work interactively with it?
ASKER
So basically what I want to do is create a py script that will call a cmd prompt to navigate to c:\program files\microsoft office\Office v# and call upon msaccess.exe and then call upon a command line switch to compact and repair a database. CMD LINE syntax is below.
1) run cmd.exe
2) cd "c:\program files\microsoft office\"
3) msaccess.exe /compact /repair "source mdb file path"
1) run cmd.exe
2) cd "c:\program files\microsoft office\"
3) msaccess.exe /compact /repair "source mdb file path"
What about something similar:
import subprocess
import os
def mdb_repair(mdb_path):
os.chdir("C:\Program files\Microsoft Office")
command = 'msaccess.exe ' + mdb_path
result = subprocess.check_output(command, shell=True)
return result
mdb_repair('c:\\my_database.mdb')
ASKER
Itpitt -
When you put + mdb_path is that actually a variable or do I put the physical path to the mdb there in quotes?
When you put + mdb_path is that actually a variable or do I put the physical path to the mdb there in quotes?
ASKER
Itpitt-
This is what I have:
I get the following error:
This is what I have:
import subprocess
import os
def mdb_repair(mdb_path):
os.chdir("C:\\Program Files\\Microsot Office\\Office15")
command = 'msaccess.exe ' + mdb_path
result = subprocess.check_output(command, shell=True)
return result
mdb_repair("C:\Test\AR001.mdb")
I get 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 10, in <module>
mdb_repair("C:\Test\AR001.mdb")
File "C:\Users\imelendez\Desktop\python\CNR_AllFiles.py", line 5, in mdb_repair
os.chdir("C:\\Program Files\\Microsot Office\\Office15")
FileNotFoundError: [WinError 3] The system cannot find the path specified: 'C:\\Program Files\\Microsot Office\\Office15'
@ltpitt: Be careful with the line 5. Backslashes must be doubled or the literal should be prefixed as raw string like this r'C:\Program files\Microsoft Office'. Actually, it is more usual and less error prone to use normal slashes as in UNIX based systems -- it works also for Windows. So, 'C:/Program files/Microsoft Office'.
@sj77: The double quotes and single quotes for string literals are the same. You can choose. But single quotes are more native for Python. The quotes are not part of the string value.
At the line 10 the 'c:\\my_database.mdb' is passed as the argument. The mdb_path is a variable that contains that value. The + does a string concatenation here. No quotes are added to the value. So, occasionally, you may need to add double quotes inside the value if the called command line utility requires them -- if you pass the command as a string. There is also alternative way when you pass the command as the list of parts (as if parsed from command line).
For shell-like scripting, have a look also at the shutil module.
@sj77: The double quotes and single quotes for string literals are the same. You can choose. But single quotes are more native for Python. The quotes are not part of the string value.
At the line 10 the 'c:\\my_database.mdb' is passed as the argument. The mdb_path is a variable that contains that value. The + does a string concatenation here. No quotes are added to the value. So, occasionally, you may need to add double quotes inside the value if the called command line utility requires them -- if you pass the command as a string. There is also alternative way when you pass the command as the list of parts (as if parsed from command line).
For shell-like scripting, have a look also at the shutil module.
ASKER
@pepr can you check my code and tell me where I am making the mistake? I think I am following you but I could be misunderstanding.
error output:
import subprocess
import os
def mdb_repair(mdb_path):
os.chdir('C:/Program Files/Microsot Office/Office15')
command = 'msaccess.exe ' + mdb_path
result = subprocess.check_output(command, shell=True)
return result
mdb_repair('C:/Test/AR001.mdb')
error output:
========= RESTART: C:\Users\imelendez\Desktop\python\CNR_AllFiles.py =========
Traceback (most recent call last):
File "C:\Users\imelendez\Desktop\python\CNR_AllFiles.py", line 10, in <module>
mdb_repair('C:/Test/AR001.mdb')
File "C:\Users\imelendez\Desktop\python\CNR_AllFiles.py", line 5, in mdb_repair
os.chdir('C:/Program Files/Microsot Office/Office15')
FileNotFoundError: [WinError 3] The system cannot find the path specified: 'C:/Program Files/Microsot Office/Office15'
Use a commander or the File Explorer to see whether your Office tools are really located at 'C:/Program Files/Microsot Office/Office15'. It can possibly be 'c:/Program Files (x86)/Microsoft Office/Office1X' (notice the (x86) if you have a 32-bit version), and/or possibly a different version of Office instead of 1X.
ASKER
@pepr -
I did as you instructed and the file path i stated was correct. I ran it via command line as a test and it executed correctly with no issues. When I run it with python I have issues.
I updated the code to look like this:
The error I got was:
I did as you instructed and the file path i stated was correct. I ran it via command line as a test and it executed correctly with no issues. When I run it with python I have issues.
I updated the code to look like this:
import subprocess
import os
def mdb_repair(mdb_path):
os.chdir("C:\Program Files\Microsot Office\Office15")
mdb_path = ("C:\Test\AR001.mdb")
command = 'msaccess.exe' + mdb_path
result = subprocess.check_output(command, shell=True)
return result
mdb_repair(mdb_path)
The error I got was:
========= RESTART: C:\Users\imelendez\Desktop\python\CNR_AllFiles.py =========
Traceback (most recent call last):
File "C:\Users\imelendez\Desktop\python\CNR_AllFiles.py", line 11, in <module>
mdb_repair(mdb_path)
NameError: name 'mdb_path' is not defined
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
ASKER
Wow did an outstanding job at not only fixing my problem but also explaining where I had made mistakes. I am an entry level programmer and to learn in such a easy way was super helpful.
ASKER
@pepr las question. My end goal was to pass a switch.
In command line I would have gone to cd "C:\program files\microsoft office\office15" > once in the path I would call upon the msaccess.exe> then used the two switches I need> /compact /repair and then the file path of the MDB> msaccess.exe /compact /repair "C:\Test\AR001.mdb"
How would I pass those switches here in my script?
In command line I would have gone to cd "C:\program files\microsoft office\office15" > once in the path I would call upon the msaccess.exe> then used the two switches I need> /compact /repair and then the file path of the MDB> msaccess.exe /compact /repair "C:\Test\AR001.mdb"
How would I pass those switches here in my script?
result = subprocess.check_output([
'C:/Program Files/Microsoft Office/Office15/msaccess.exe',
'/compact',
'/repair',
mdb_path])
The formatting is not that important here -- just to make it more visible. Notice the comma that separates the added elements in the list.My guess is that the function should have the switches always used for the msaccess. However, it is also possible to pass them via arguments of the function. Now, not exactly for the switches, but to show some extra argument. Let's say, that you want to enhance the function so that it was possible to pass a different version of msaccess.exe (location). Let's say, you may have a different function (implemented in future) that would get the location of msaccess.exe dynamically, somehow. You can think in advance and rewrite (the fancy word is to "refactor") the code like this:
#!python3
import subprocess
import os
def mdb_repair(mdb_path, msaccess='C:/Program Files/Microsoft Office/Office15/msaccess.exe'):
result = subprocess.check_output([msaccess, '/compact', '/repair', mdb_path])
return result
if __name__ == '__main__':
mdb_repair('C:/Test/AR001.mdb')
Notice the second argument of the function. The argument is assigned by the full name of msaccess.exe that you use now. Because it is assigned a default value, you do not need to write the argument when calling the function. But in future, you can pass another value to the argument.Now notice that the subprocess.check_output uses the variable msaccess as the first element of the list. The other elements (two switches and the database file) are passed the same way. Possibly, it is more readable. At least it is not more difficult to understand.
You should always try to make your source as readable as possible. It may happen, that you will look at it few months/years later. You will be pleased if you will be able to see exactly how it works without the need to decipher the meaning. If it looks better than previous version, it may a be better solution.
Now notice that the code is so simple, that introduction of the result variable does not make it simpler. (It may make it simpler in more complex situations, but this is not the case.) So, you can even simplify it:
#!python3
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')
The string in trippled double quotes (this is the convention) documents the functionality. Some editors are able to display the string when you type the function name (when you want to call it). Some other tools will get the string and will generate the documentation for your program. (It makes sense when the project gets bigger.)
ASKER
Thank you very much!
ASKER
Below is the finished working code. Thanks @Pepr
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')
Great job and good learning material, @pepr!