You have a number of programs which need to be run in a sequence. You need an easier programming environment than a shell to control the flow. Python is widely used for utilities programming, graphical front-ends for Linux command line scripts by organisations like Fedora and Ubuntu. Python has an excellent set of built-in modules for interfacing with the OS and the system. So, start the python interpreter and get a list of modules available: >>>help('modules') Spend a few minutes looking at the long list of modules you can use. You should notice that there are two modules with names which remind us of the work we need to do - 'os' and 'sys'. You will want to know what each of these modules does. So, try: >>>help('os') The os module provides os dependent functions for managing files, directories and execution of programs. The first method you can try is 'system'. >>> import os >>> error = os.system('OpenOffice') sh: openoffice: command not found >>> print error 32512 You realise that the command for starting open office is ooffice (works on Fedora and Ubuntu) or soffice depending upon distribution/installation. So, try again but make sure that you close ooffice if you are using it: >>> error = os.system('ooffice') >>> print error 0 Open office starts but the control does not go back to the Python program. You will notice that the print statement is executed only after you have closed open office. You need to keep the open office started and running in the background. An easy option is that we can use the option '&' to run the program in the background. So, try: >>> error = os.system('ooffice &') >>> print error 0 This time open office starts up and the print statement is executed. You can work in both applications. There remains a slight hitch. You may wish to stop the program. You need to spawn another program and have control over it. You can have a look at the spawnlp method and that seems appropriate. It takes a 'no wait' option and returns the process id. So, try: >>> pid=os.spawnlp(os.P_NOWAIT, 'ooffice') >>> print pid 12058 >>> os.kill(12058,9) Open office should close. Now you can explore the 'sys' module. Two items will be useful from this module. The exit method and the list, argv, which contains the command line parameters passed to the python program. Write the following code in test_params.py: import sys import os for param in sys.argv: print 'Parameter = ', param Now, from the command line, run $ python test_params.py loans_v2.py Parameter = test_params.py Parameter = loans_v2.py Notice that the first parameter is the name of the python script and the other parameters follow. From the command line, try: $ gedit test_params.py >>> p= os.spawnlp(os.P_NOWAIT,'gedit', 'test_params.py') >>> print p 12953 The editor starts but does not open the file. As we had noticed above, Linux expects the first parameter to be the identifier of the application. So, you can pass one additional parameter as follows: >>> p= os.spawnlp(os.P_NOWAIT,'gedit','gedit', 'test_params.py') >>> print p 12997 The editor has opened the file as expected. The WorkflowYou now have the basic tools at your disposal to start integrating the various tasks from last month's programs. You can start creating a file, workflow.py: import os pid=os.spawnlp(os.P_NOWAIT,'ooffice','ooffice','-accept=socket,host=localhost,port=2002;urp;','-invisible') os.system('python db2oo.py') Now, try running this program from the command line: $ python workflow.py File "db2oo.py", line 18, in <module> calc = oo_calc() File ".... open_office.py", line 14, in oo_calc 'uno:socket,host=localhost,port=2002;urp;StarOffice.ComponentContext') open_office.NoConnectException: Connector : couldn't connect to socket (Success) You get an error. A little experimentation will lead you to the conclusion that the open office program has started but is not yet ready for accepting connections. So, you will need to wait before starting the rest of the script. You should revise your workflow.py as follows: import os import time def start_oo_daemon(): # Start Open Office in background mode pid=os.spawnlp(os.P_NOWAIT,'ooffice','ooffice', '-accept=socket,host=localhost,port=2002;urp;','-invisible') print 'Open Office started. Wait a few seconds to connect' time.sleep(4)
start_oo_daemon() print "Load Data from db" os.system('python db2oo.py') # stop background copies of soffice & soffice.bin os.system('pkill soffice') # Manually edit the spreadsheet os.system('ooffice /home/anil/workbook.ods') start_oo_daemon() print "Store data back in db" os.system('python oo2db.py') # Clean up os.system('pkill soffice') You need to run the open office in background twice. So, convert it into a function. A second point to note is that the command ooffice starts 2 programs – soffice and soffice.bin. The pid is of the first. Unfortunately, the second one is not killed if you have run open office in the background mode and you kill the first one. A simple solution is to use the pkill command as above. By the way, you can leave out the '-invisible' option while developing and testing. Using Command Line ParametersA well-written program should not depend on hard-coded file names. So, you should accept command line variables. The files needed are the friends and items databases and the temporary spreadsheets workbook. Typically, Linux utilities use the pattern '-o value'. You may decide to use '-i' for items, '-f' for friends and '-w' for workbook. So, create a file test_params.py: import sys print 'The number of arguments',len(sys.argv) print 'The script name',sys.argv[0] index=1 while index < len(sys.argv): if sys.argv[index] == '-i': items_db = sys.argv[index + 1] print 'Items ', items_db elif sys.argv[index] == '-f': friends_db = sys.argv[index + 1] print 'Friends ', friends_db elif sys.argv[index] == '-w': workbook = sys.argv[index + 1] print 'Workbook ', workbook else: print "Syntax Error ", sys.argv[index] sys.exit() index += 2 You should now execute this script, e.g. $python test_params.py $python test_params.py -i items.db $python test_params.py -i items.db -w workbook.ods $python test_params.py -f friends.db -w workbook.ods -i items.db This script should now be integrated with the workflow.py. Since it will require changes in the code from the last month's article and is not difficult, you can do this as an exercise. Using Tkinter for accepting OptionsA second exercise worth doing is that you need not restrict yourself to just command line parameters. If the parameters have not been given, you could bring up a tkinter form as discussed in an earlier article. You can type the following in tk_params.py and expand it : import Tkinter import tkFileDialog
def tk_get_params(): root = Tkinter.Tk() items_db = tkFileDialog.askopenfilename( parent=root, initialdir='/home/anil', title='Please select Items DB') workbook = tkFileDialog.asksaveasfilename( parent=root, initialdir='/home/anil', title='Please select Worksheet Name') return items_db, workbook
print tk_get_params() In the case of items_db, the file must exist; so, askopenfilename is the useful method. In the case of workbook, if the file exists a warning that an existing file will be overwritten is useful; hence, asksaveasfilename is the appropriate method. As you have tried, it is easy to add existing widgets and quickly capture desired parameters conveniently. The hardest part of using tk widgets is finding the documentation for using them! The best place to learn more about various Python modules is by using the python docs – http://docs.python.org/. Usage of widgets is best explored by using Google. You may well think that the world is moving to Web2.0 so what's the point of continuing with pre-web programming. So, next time you will explore how to web-enable your application for keeping track of your loaned items. |
Python For Friends >