Wiley.Mobile.Python.Rapid.prototyping.of.applications.on.the.mobile.platform.Dec.2007 (779889), страница 46
Текст из файла (страница 46)
If you think about our explanation of the global symbol tablein the previous section and how the keyword global relates to it, thisoutcome should feel logical, as each module has a symbol table of its own.236EFFECTIVE PYTHON FOR S60For instance, if you had declared the variable word global in mymodule, it would not have been visible to Example 107 automatically.This is beneficial, since you can treat each module as a separate unitindependently from other modules.Whenever you feel that your application gets too complex to handle inone file, separate it into several modules.
Also, if you feel that a functionwould be useful for many applications, place it into a separate moduleso it can be imported to any application that needs it.10.3.2 Extending Python for S60 in Symbian C++It is also possible to extend PyS60 using Symbian C++. As a matter offact, the standard PyS60 API is mostly implemented this way. Althoughthis approach is much more complicated than making custom modulesin Python, it enables you to connect directly to low-level services ofSymbian OS.For instance, if you want to use an accelerometer that may be builtinto your phone and it cannot be accessed using the standard PyS60 API,making a C++ extension is an appropriate choice.To write a C++ extension for PyS60, you need:•a PC with Windows•C++ SDK for the S60 platform appropriate to your phone•Python for S60 plug-in for the S60 C++ SDKFor details on how to write C++ extensions, see the PyS60 documentation and PyS60 wiki.10.3.3Automatic UpdatingA file containing a PyS60 module, or any other source code in Python,is just an ordinary text file.
Consequently, you can handle these sourcecode files as any other files in Python. In particular, it is possible todownload a source code file from the web and save it to E:\Python\ orE:\Python\Lib, which makes it visible to the PyS60 interpreter.This means that you can update your PyS60 programs using PyS60!Example 108 should clarify this.Example 108: Updating PyS60 code from the webimport urllibCODE = "mytest.py"URL = "http://www.myownserver.com/pycode/"CUSTOM MODULES AND AUTOMATIC UPDATING237code = urllib.urlopen(URL + CODE).read()f = file(u"E:\\Python\\" + CODE, "w")f.write(code)f.close()print "File %s updated successfully!" % CODEAs you can see, it uses the standard urllib.urlopen() function todownload a file from the web, like many examples in Chapters 8 and 9.In this case, the file name CODE refers to a PyS60 source code file thatwe have made available to a web server at URL.
Change the URL topoint at your own web folder containing a file named mytest.py. Thescript downloads the file and saves it to the E:\Python\ directory, so itcan be found in the PyS60 interpreter’s Run script menu. After runningExample 108, a new file mytest.py should appear there as a newPython script.It is impossible to overemphasize the usefulness of this little script. Ithas proven vital in projects carried out by the authors of this book in tworespects. First, for some PyS60 developers, it can be the fastest way toupload code to the phone during development. If you are familiar withwebsite development and you can edit files in the web easily, you canplace and edit your PyS60 files on the web as well. When you need to testthe code, you just execute this program and the source files are updatedon your phone instantly.
This is particularly convenient if you can useWiFi on your phone for network connection and you can run a local webserver on your PC.Second, this method has proved to be valuable in production settingsas well. The authors of this book designed and implemented a large-scaleurban game, called Manhattan Story Mashup, in New York in September2006. More information about the game can be found in Section 11.2.Because of many uncertainties, we were reluctant to freeze the gameclient a long time before the actual event.
However, the players weregiven phones to play the game a week before the event, so we needed amethod of updating the last-minute fixes to the players’ phones.Our solution is depicted in Figure 10.1. As you can see, the figureshows a PyS60 interpreter. However, we modified the application menuof the interpreter slightly. This is not difficult, since the PyS60 interpreterUI is implemented in Python (naturally!) and PyS60 is distributed as opensource, so you are free to modify it in any way.We added an Update StoryMashup item to the menu, as shown inthe figure.
This item executed a function similar to Example 108, whichupdated the game client code from the web.Finally, just before the game started, we instructed our 160 playersto update the latest version of the game client simply by selecting thisitem.
As a result, all the players were using an identical version of theclient, which included our last-minute changes. This method was a reallife saver.238EFFECTIVE PYTHON FOR S60Figure 10.1 Automatic updating10.3.4Simple Plug-In MechanismWe may take automatic updating even further. Not only can you download PyS60 modules from the web using Python, but you can also decidewhich modules to import at run time.This makes your applications infinitely extensible. Depending on theuser input, the physical environment or any other parameter, you canmake your application request new functionality from the web. This leadsto opportunities that come from science fiction, but, in simple terms, itallows you to easily make a plug-in mechanism for your applications.Example 109: Plug-in mechanismimport urllibURL = "http://www.myownserver.com/pycode/"def download_plugin(plugin_name):filename = plugin_name + ".py"code = urllib.urlopen(URL + filename).read()f = file(u"E:\\Python\\Lib\\" + filename, "w")f.write(code)f.close()return __import__(plugin_name)plugin_name = appuifw.query(u"Give plug-in name", "text")print "Downloading plugin", plugin_nameplugin = download_plugin(plugin_name)print "Plugin loaded!"plugin.askword()PROGRAM PATTERNS239Example 109 wraps the download functionality of Example 108 inthe function download plugin().
As in the previous example, itdownloads a PyS60 source code file from a specified URL on the weband saves it to a local directory. However, in this case, the file is saved toE:\Python\Lib, which makes the file able to be imported as a custommodule, as we saw in Example 107.The magic happens with Python’s specialimport () function.Normally, when you import a module to your program, you have tospecify the module’s name in your source code, after the importstatement. In contrast, theimport () function lets you import amodule at run time, by giving the module’s name in a string.
It returnsthe imported module as an object that you can use in the usual way.In this example, the user can specify the plug-in name, plugin name,that is loaded from the web. Let’s assume that you type ‘myplugin’ in thedialog. Then, the download plugin() function tries to download thefile http://www.myownserver.com/pycode/myplugin.py.You should make sure that such a file is available. When the filehas been downloaded successfully, it is saved to E:\Python\Lib, afterwhich it can be imported as any other module.In this case, we import the module immediately using theimport() function.
The function download plugin() returns the newlyimported module in the variable plugin. We assume that the modulecontains a function called askword() that is then called in the last lineof the example, which demonstrates that the new plugin module canbe used just as usual.Note that this example does not contain any precautions for exceptions.A real plug-in mechanism should make sure that the plug-in file isavailable and that it contains the necessary functions. This is easy toaccomplish with try–except blocks, as described in Chapter 6.10.4 Program PatternsWe have gone through over 100 code examples.
The examples havedemonstrated a wide array of topics from string handling, GUIs, MP3players and 2D graphics to GSM locationing, AppleScript, JSON gatewaysand web services. From one point of view, this book could be considereda large grab bag of interesting things that one can do with a mobile phone.On the other hand, one could claim that many examples differ merelyon the surface level from others. You have probably noticed this phenomenon as well: many new modules and examples that we haveintroduced might have felt understandable to you at first sight. Eventhough the module name and, of course, its functionalities were differentfrom what you had seen before, the new example often shared a similarstructure with earlier examples.240EFFECTIVE PYTHON FOR S60This book is arranged according to subject areas, such as graphics,Bluetooth and network programming.
Given that we believe that mostof our readers are more interested in cool applications than theoreticalcomputer science, this grouping felt appropriate.However, we could have grouped the examples according to theprogram pattern that they follow. That is, instead of the subject area,we might categorize the programs according to how they are structuredinternally and how they interact with the outside world.The following list presents one such categorization. For each pattern,we give a partial list of examples that follow this pattern. Note that a singleprogram may be based on several interleaved patterns.
For instance, theGSM cell ID mapper (Example 49) follows both the updating and theapplication patterns below.•Script: these are small examples that execute sequentially fromthe beginning to the end and do not wait for external events tooccur. Scripts are handy for automating small tasks. For instance,Examples 43, 63 and 79 follow this pattern, as well as all the examplesin Chapter 3.•Application: these are examples that are based on the S60 applicationuser interface framework.
The user may interact with the application,for example, by way of the application menu. Internally, the coderelies on event callbacks. For instance, Examples 12, 49 and 73 andall the examples in Chapter 9 follow this pattern.•Updating: this pattern is useful in cases where the program mustupdate some data periodically. Typically, this is accomplished usingthe e32.Ao timer object that is set to call a function at regularintervals. The GSM cell ID mapper in Example 49 and EventFu inSection 9.3 follow this pattern.•Event-driven: external events can originate from some other sourceas well as the user interface.