ExampleSourceCode:[Link]
zip
ThisarticleoriginallyappearedintheSeptember2003issueofFoxTalk.
Ifyouenjoythisarticle,pleaseconsidersendingaPayPaldonationtop@[Link]!
ExploringPythonfromaVisualFoxPro
Perspective
PaulMcNett
VisualFoxProisquitecapableinalmostallaspects,exceptforapplicationdeploymentaccordingtoMicrosoft,youmay
[Link],IdiscoveredPython,an
opensourceprogramminglanguagethatisacompellingchoiceforseasonedVisualFoxProdevelopersanditrunson
multipleplatforms!Inthisarticle,I'llintroduceyoutoPython,andshowyouhowtoaccessVisualFoxProdatawithit.
ManyVisualFoxProdevelopersfeelthattheirchoicesofdevelopmentenvironmentsareeffectivelylimited
[Link],[Link]
compelling,capable,[Link]
linkagainsttheWindowsGUI,andarethereforelimitedtorunningontheWindowsplatform(unlessyou
wanttouseaworkaroundsuchasWineoravirtualmachinesuchasWin4LinorVMWare).Thislimitation
[Link],[Link],suchas
thevariousflavorsofC,C++,andJava,thataremultiplatformcapable,butinmyquestforamultiplatform
programminglanguage,onerosetothetoppreciselybecauseofitssimilaritiesinlotsofwaystothe
experienceofprogramminginFoxPro.I'dliketosharewhatI'velearnedaboutPython,andhowthis
knowledgemayapplyvisavisVisualFoxPro.
YouareprobablyaskingwhyshouldIcare,whyshouldIlearnyetanotherlanguage?TothatI
mustanswer:justhavealook,followmytutorialandseewhatPython'[Link]
isn'tforyou,youhaven'[Link],asIknowyou
will,you'llhaveanothervaluabletooltoputinyourkit.
PythonataGlance
Sportingasnakeicon,PythonwasactuallynamedaftertheMontyPython'sFlyingCircusBBCtelevision
show,byitscreator,GuidovanRossum,startinginthelate1980'[Link]
ofverysmartpeoplethatareonthewholeveryhappytosharetheirrecipesandhelpnewbiesgetstarted.
Pythonisaninterpretedlanguagewithanelegantandreadablesyntax,andlikeVisualFoxProyou
canmixandmatchOOPwithfunctionalprogramming,allvariablesareineffectvariants,andthereisa
[Link]
byadditionalmodulescontributedbydevelopersallovertheworld.
Pythoncomeswithaliberalopensourcelicense,whichmeansthatyouarefreetomodifyand
[Link],anddoesn't
haveanydependenciesonanyGUI,sothereforeisquiteportabletoallknownplatforms,evenincluding
DOS,olderversionsofWindows,[Link],andas
longasyouhaven'tlinkedagainstanymodulesthatareplatformdependent,yourprogramwillexecuteon
[Link],MacintoshOSX
isalsowidelysupportedandanyPythonprogramcanbemadetorunonmanyotherplatformsaswell.
ErrorhandlingiseasywiththenowubiquitousTRY...CATCH...FINALLYblockswhichcanbe
[Link],andyoucanmakeyourownaswellby
[Link]
actuallyhavetotrytoignoretheseimportantfeatures.
Pythonisstrictcase:[Link],dependingonthe
operatingsystemyouarerunningiton,capitalizationmayormaynotmatterwithregardtofileand
directorynames.
Functionsarefirstclassobjects,whichmeansthatyoucangetanobjectreferencetoafunction
(eitherastandalonefunctionoramethodofaclass),[Link]
collectionhappensautomaticallyinthebackground,andcanbeoverriddenifneeded.
Sourcecodeisplaintext,whichmeansyoucanuseyourfavoriteeditor,andPythonsourcefiles
(scripts)[Link]
Pythoninterpreterasneeded,[Link],[Link]
also,asinFoxPro,fireuptheinteractivePythoninterpreter,[Link]
interactiveinterpreterisactuallymorecapablethanVisualFoxPro'scommandwindow,inthatyoucaneven
executecontrolstructuresanddefineentireclassesorfunctions.
Python,unlikeVisualFoxPro,doesnotcomewithanygraphicalwidgetsforconstructing
[Link],however,distributedwithamultiplatformGUItoolkitcalledTkinter,which
[Link](PyQtandwxPythontonamethe
toptwo),[Link]
nicenotcarryingalongtheGUIbaggagewhenagivenprogramdoesn'tneedit,anditisveryliberatingto
beabletochooseforyourselftheGUIthatworksbestforyou.
PythoncomeswitharudimentaryIntegratedDevelopmentEnvironmentcalledIDLE,althoughI
usuallyjustusethecommandlinebecauseIfindthatsimplerandmoreefficientformypurposes.I'llutilize
IDLEinthistutorialsincemostWindowsdevelopersaremorecomfortableusingaGUIthanacommand
line.
InstallingPython
PythoniseasilyinstalledonWindowsbydownloadingandrunningtheinstallerat
[Link]
installation,youmayinstallitonotherplatformsaswellbyfollowinglinksat
[Link]
everythingyouneed.Pleasealsoinstallthewin32allextensions
([Link]
Windowsdevelopment.Pythonandthewin32allextensionsarecompletelyfree,asinfreedomandasin
beer.
AfteryouinstallPythonandthewin32allextensions,I'llguideyouthroughashorttutorialand
[Link]'lllearnPython'sbasicdatatypes,
controlstructures,andOOPimplementation.
AShortTutorialDataAccessinPythonandVisualFoxPro
[Link],
you'llbeintroducedtoPython'[Link],InolongerusenativeVisualFoxPro
tables,butratherchoosetouseMySQL(orotherdatabaseservers)[Link],I
connecttoMySQLusingtheMyODBCdriver,andfromPython,IconnectusingtheMySQLclientlibrary
[Link],I'lljustusenativeVisualFoxProtablesandthenmanipulate
thosetablesbothfromVFPandPython.
Thefirstthingyou'[Link]
aremanywaystousePython,I'llguideyouthroughusingthePythoncommandlineinterpreteras
implementedbyIDLE,[Link],underPrograms/Python
[Link](PythonGUI).DoingthiswillbringupawindowtitledPython
Shell,[Link]>>>.To
aquaintyouwiththemostbasicPythoncommands,followtheseexamples:
>>>printhelloworld!#thestringisoutput
helloworld
>>>helloworld!#astringobjectisoutput
'helloworld'
>>>1+2#Addition
3
>>>12#Subtraction
1
>>>75*57#Multiplication
4275
>>>1/2#Divisionofinteger
0
>>>1.0/2#Divisionoffloat
0.5
>>>breakfast=eggs#bindingnametostring
>>>count=3#bindinganothernametointeger
>>>#simpleoutputformatting/linecontinuation:
>>>printforbreakfastyou'llhave%d%s.\
%(count,breakfast)
forbreakfastyou'llhave3eggs.
>>>importsys#importingexternalmodule
>>>[Link]
'win32'
>>>importodbc#testifwin32allisinstalled
>>>defmyFunction(string):
printMyFunction:,string
returnyes
(pressreturntwiceheretogetthepromptback)
>>>printmyFunction(hereIam!)
MyFunction:hereIam!
yes
>>>printmyFunction
<functionmyFunctionat0x8176084>
Okay,[Link]
andgettingusedtoPython'ssyntax.(Hmmmm,soundfamiliar?Kindalikeadotprompt?OrtheVisual
FoxProCommandWindow?)Andyougetadditionalbenefitsfromusingtheinteractiveinterpreterwith
IDLE:[Link],youlearnedseveral
thingsintheabovesession:commentscanappearonalineoftheirownorinline,alinecanbecontinued
withthebackslashcharacter,normalPythonscriptscanbeimportedintootherPythonscriptsasmodules,
thebasicprintoutputfunctionalityisadequateforquicktesting,andfunctionsarefirstclassobjectsand
[Link]'tgetanyerrorsimportingtheodbcmodule,youareready
tocontinuewiththistutorial.
MygoalistointroduceyoutothesimplicityandeleganceofPython,andI'lldothisbyshowing
youhowyoucanaccessandmanipulatedatabasetablesfromPythoncode.I'llwalkyouthroughthedesign
ofsometesttablesfromVFP,accessingandmanipulatingthetablesfromVFPwiththeFoxProODBC
driver,andthenaccessingandmanipulatingthetablesfromPythonusingthesameODBCdriver.
Firstofall,makesureyouhavetheVisualFoxProODBCdriverinstalled(opentheODBC
Administrator,gotothedriverstab,[Link],whichyou'll
needwhenyouentertheconnectstringlater.Myversionis6.01.8629.01,andthenameisMicrosoft
FoxProVFPDriver(*.dbf).Ifyoursisnameddifferently,you'llhavetosubstituteyournameinmy
examples.
[Link],andfollowalonginthecommandwindow:
mkdirc:\temp\pytest
cdc:\temp\pytest
createtablemenu(iidi,citemc(32),;
npricen(8,2))
insertintomenu(iid,citem,nprice)values;
(1,Pancakes,4.50)
insertintomenu(iid,citem,nprice)values;
(2,CoffeeCake,2.89)
insertintomenu(iid,citem,nprice)values;
(3,TofuScramble,5.00)
use
*connectusingODBC:
cString=[driver=];
+[{MicrosoftFoxProVFPDriver(*.dbf)};];
+[SourceType=DBF;SourceDB=c:\temp\pytest\]
iHandle=c:/temp/pytest/"
*iHandleshouldcontainapostivevalueifit
*returnsa'1'value,itmeansthecommand
*failed
=SQLEXEC([Link],select*frommenu)
BROWSE
Ifyouseeyourthreerecordsinasqlcursorcalledsqlresult,[Link]
samethingfromPython.
Beforegoingon,IshouldbackawayatthispointandexplainthatPythonconsistsofacorethatis
[Link],orthey
mayhavecomefromoneofhundredsofdevelopersworldwide,[Link]
pointI'mmakinghereisthat,unlikeVFP,Pythondoesnotloadupalotofbaggagethatyoumayormay
noteveruse,[Link],yougetto
choosethemodulesthatworkbestforyou,insteadofrelyingononevendortomaketheonecorrectchoice
foryou,orrefusingtoprovidefunctionalitythatyouneed.
Accessingdatabasesrequirestheimportingofanappropriatedriverforthedatabaseinquestion,
andtomakeitalesslowlevelofanexperienceI'veborrowedarecipefromThePythonCookbookcalled
'LazyDB',[Link]'Aquila,andwrappeditwith2layersofmyownmodules,onethat
definesadbAccessbaseclass,[Link]
subclassescouldbemadetoaccessotherbackenddatabases,suchasMySQLorMicrosoftSQLServer.
Anyway,thereare3filesinthedownloadsectionthatyouneedtosaveforthetutorialtowork.
Theyare:[Link],[Link],anddbaccess_vfp.[Link]:\temp\pytestcode\.dbaccess_vfp.py
containsasubclassofdbAccess,[Link]
[Link].
Takealookatthesethreefilesinatexteditor(hint:openIDLE,thenFile/Open,andviewthefiles
thatway,asyougetthebenefitsofsyntaxcoloring).Notethateveryscriptexceptforlazydbhasanimport
statement.dbaccess_vfpimportstheodbcdriver,[Link]
projects,Iactuallyuseadbaccess_mysqlscriptthat,insteadofimportingodbc,importsMySqlDbwhich
[Link]
commondbaccessandlazydbmodules.
Anyway,takealookatthecodeinthesethreefilesasyouarenewtoPython,youwon't
completelyunderstandit,butyoushouldnoticethatthecodeisreadableandtheclassdefinitionsare
simple.Noticeatthebottomofdbaccess_vfp.py,[Link],ineffect,awayof
[Link](bytyping'python
dbaccess_vfp.py'attheDOScommandline),[Link]
verysimilartotheconventiongoodVFPdevelopershaveadoptedofputtingunittestcodeintheirprogram
classesthatwillexecutewhenyourunthecodeasaprogram,butnotwhenyouinstantiateaclassfromthat
[Link],youwouldputsuchtestcodeatthetop,butinPythonitmustgo
[Link],whydon'tyourundbaccess_vfp.pyandseeifeverythingisworkingcorrectly.
OpenupaDOScommandline([Link])anddothefollowing:
c:
cdc:\temp\pytestcode
pythondbaccess_vfp.py
Ifyousawthetestoutputalongwiththe3menuitems,[Link]
TraceBackmessage(Python'sdefaulterrorhandler),youprobablyneedtoeditdbaccess_vfp.pytochange
[Link]
[Link]
messagethatthepythonexecutablecouldnotbelocated,thenyouneedtomanuallyaddthePython2.2
[Link],[Link],youcan
probablygetawaywithsimplytyping:
dbaccess_vfp.py
Okay,sothescriptruns,provingthatyou'[Link]
tables,soitistimetostartIDLEagainandfollowalonginthePythonshell.I'llbeimportingthe
dbaccess_vfp.pymodule,whichisstillsittinginc:\temp\[Link]'tinPython'ssearchpathfor
modules,I'[Link],this
oneintroducesyoutoabasicPythontype:theList.
PythonisparticularlywellsuitedfordealingwithdatabecauseofitsList,Tuple,andDictionary
[Link],andsequencescancontainothersequences,resultinginapowerful
[Link],andisspecifiedbyusingsquarebrackets([]).
Contrastthistoatuple,[Link]
().Listsareagreatwaytohold'records',wherebyeach'record'isanotherlistof'fields'.Anyway,the
pathingissue:
>>>importsys#basicsystemfunctions
>>>[Link]
(Iomittedtheresults,butdothisyourself,
andyou'llseealistofstrings)
>>>#appendourpath:
>>>[Link](c:\\temp\\pycode)
Nowthatyouhavethepathsetup(didyounoticethatthelistisactuallyanobjectwithanappend()
method?)youcanfollowalongwiththefollowinginteractivesessiontoreadfromandmanipulatethetest
data:
>>>#importintotheglobalnamespace:
>>>fromdbaccess_vfpimport*
>>>#getarecordset:
>>>menu=dbVFP().dbRecordSet(select*
frommenu)
>>>#showalltherecords(notetheclean
>>>#iterationstyle):
>>>foriteminmenu:
[Link],[Link]
(twoCR'stoexittheiterationblock)
[Link],timetohavesomefunbyupdatingandinsertingrecords:
>>>#thistimegetapersistentobjectreference
>>>#todbVFP:
>>>vfp=dbVFP()
>>>[Link](updatemenusetcitem=
'PancakesandSpam'whereiid=1)
>>>#thistimedefineafunctionwecancall
>>>#overandoveragain:
>>>defshowAll():
menu=dbVFP().dbRecordSet(select*from
menuorderbyiid)
forrecordinmenu:
[Link],[Link],\
[Link]
>>>#nowwhenwechangesomething,wecanjust
>>>#callshowAll():
>>>[Link](insertintomenu
(iid,citem,nprice)values
(4,'RiceCakesandWater',14.50))
>>>showAll()
Playaroundinteractivelyforawhile,[Link]
maynotbeallthatexcitedyet,becauseyou'venoticedthatsofaritsbeenalltextoutput,nofamiliar
[Link],tointroduceyouPythonbyshowingyouone
[Link],therearemanywaystocreateprofessionalGUIapplicationswith
[Link]'tfeeltotallyleftoutinthecold,hereisalittleteasertoshowyouhoweasyitcan
betoaddagraphicalinterfacetoyourapplication(enterthiscodeinthePythonShellinteractively,orif
youarefeelingmoresureofyourself,makeitintoascriptandthenexecuteit):
importsys,Tkinter
[Link](text=Enoughspamforya?).pack()
[Link](text=Bye,command=[Link]).pack()
[Link]()
PythonResources
Pythonissupportedbyacommunityofenthusiasticvolunteers,inacademiaandtheITindustry,from
[Link],at[Link]
areplentyoftutorialsandlotsofdocumentationtheretokeepyoubusylearningthisexcitinglanguage.
Thereisalsoamailinglist/UseNetgroup(pythonlist@[Link]/[Link])thatrangesfrom
newbietoultratechnicalandthatI'[Link],of
whichIcanhighlyrecommendPythoninaNutshell,byAlexMartelli,O'Reilly2003asagreatdesktop
referenceandPythonCookbook,editedbyAlexMartelliandDavidAsher,O'Reilly2002,whichcontains
recipes(howto's)fromthePythoncommunity.
PythonandVisualFoxProcanworkwelltogetherinsituationswhereyouhaveadesktopapplicationanda
[Link]
[Link]
loadVFPtendstoputontheserverunlessyouhaveadedicatedserverforyourVFPwebapp,you'll
[Link],ifyoufindthatyouneedto
deployyourdesktopapplicationtoplatformsotherthanthelatestversionofWindows,youcanconsider
rewritingitinPython,[Link]
developmenttools,therearemanyalternativesoutthere,andinmyobservationsPythonisworthalook.
PaulMcNettisanindependentsoftwareconsultantinHollister,[Link]
applicationsusingVisualFoxProisstillhisprimaryfocus,heisalsousingdevelopertoolsfromtheopensource
community,includingPython,todeploytotheOSX,Linux,[Link]
p@ulmcnett.comorbyphoneat831.636.9900.