📄 index.lxp@lxpwrap=c6996_252ehtm.htm
字号:
<table border="0" cellspacing="0" cellpadding="3" width="100%"><tr><td> <div align="center" id="bldcontent"> <a href="../default.htm"><img src="../images/opendocs.png" width="63" height="76" border="0"></a> <br> <div class="symbol">Your OpenSource Publisher™</div> </div> </td></tr></table> <div align="center" class="author"> <a href="../products.lxp">Products</a> | <a href="../wheretobuy.lxp">Where to buy</a> | <a href="../bookstore.lxp">Retailers</a> | <a href="../faq.lxp">FAQ</a> | <a href="../writeforus.lxp">Write for Us.</a> | <a href="#contact">Contact Us.</a> </div> <table border="0" cellspacing="3" cellpadding="0" width="100%"><tr><td width="100%"> <div class="content"> <table border="0" cellspacing="2" cellpadding="0" width="100%"><tr><td width="100%"> <div align="center"><H4 CLASS="AUTHOR"><A NAME="AEN5">Boudewijn Rempt</A><br><a href="../../https@secure.linuxports.com/opendocs/default.htm"><img src=odpyqt125.png></a><br>ISBN: 0-97003300-4-4<br><a href="../../https@secure.linuxports.com/opendocs/default.htm">Available from bookstores everywhere or you can order it here.</a><p>You can download the source files for the book <a href="pyqtsrc.tgz">(code / eps) here.</a><hr></div> <HTML><HEAD><TITLE>A Macro Language for Kalam</TITLE><METANAME="GENERATOR"CONTENT="Modular DocBook HTML Stylesheet Version 1.72"><LINKREL="HOME"TITLE="GUI Programming with Python: QT Edition"HREF="book1.htm"><LINKREL="UP"TITLE="Creating real applications with PyQt"HREF="p4627.htm"><LINKREL="PREVIOUS"TITLE="Conclusion"HREF="x6992.htm"><LINKREL="NEXT"TITLE="Integrating macros with a GUI"HREF="x7161.htm"></HEAD><BODYCLASS="CHAPTER"BGCOLOR="#FFFFFF"TEXT="#000000"LINK="#0000FF"VLINK="#840084"ALINK="#0000FF"><DIVCLASS="NAVHEADER"><TABLESUMMARY="Header navigation table"WIDTH="100%"BORDER="0"CELLPADDING="0"CELLSPACING="0"><TR><THCOLSPAN="3"ALIGN="center">GUI Programming with Python: QT Edition</TH></TR><TR><TDWIDTH="10%"ALIGN="left"VALIGN="bottom"><A accesskey="P" href="index.lxp@lxpwrap=x6992_252ehtm.htm">Prev</A></TD><TDWIDTH="80%"ALIGN="center"VALIGN="bottom"></TD><TDWIDTH="10%"ALIGN="right"VALIGN="bottom"><A accesskey="N" href="index.lxp@lxpwrap=x7161_252ehtm.htm">Next</A></TD></TR></TABLE><HRALIGN="LEFT"WIDTH="100%"></DIV><DIVCLASS="CHAPTER"><H1>Chapter 20. A Macro Language for <SPANCLASS="APPLICATION">Kalam</SPAN></A></H1><DIVCLASS="TOC"><DL><DT><B>Table of Contents</B></DT><DT><A href="index.lxp@lxpwrap=c6996_252ehtm.htm#AEN7006">Executing Python code from Python</A></DT><DT><A href="index.lxp@lxpwrap=x7161_252ehtm.htm">Integrating macros with a GUI</A></DT><DT><A href="index.lxp@lxpwrap=x7295_252ehtm.htm">Creating a macro API from an application</A></DT><DT><A href="index.lxp@lxpwrap=x7388_252ehtm.htm">Conclusion</A></DT></DL></DIV><P>One thing that separates a run-of-the-mill application from a real tool—one that users will take refuge in day after day—is a good macro facility. Python, which was designed with ease of use in mind, is a natural choice for a macro language. Nine out of ten secretaries would choose Python over the WordPerfect macro language or Visual Basic, given the choice! Isn't it fortunate that we have already begun developing our application in Python?</P><P>This chapter deals with integrating a Python based macro facility in <SPANCLASS="APPLICATION">Kalam</SPAN>. In the course of this chapter we investigate the execution of Python code while dynamically adding actions and menu items. We also cover granting user access to a predefined API of our application objects.</P><P>Of course, the underlying mechanics of a macro facility are not particular to any GUI toolkit. And if you decide to convert your application to C++, you can still embed Python, wrap the API using <SPANCLASS="APPLICATION">sip</SPAN>, and allow your users to execute the same macros. We handle powerful stuff in this chapter, and it's well worth the effort. </P><DIVCLASS="SECT1"><H1CLASS="SECT1">Executing Python code from Python</A></H1><P>There are three basic ways to execute Python code that is not directly (i.e. imported as a module) part of your application. Single statements can be executed with <TTCLASS="FUNCTION">eval()</TT>; we already encountered <TTCLASS="FUNCTION">eval()</TT> in <A href="index.lxp@lxpwrap=c6013_252ehtm.htm">Chapter 18</A>. Strings that contain more than a single statement of Python code can be executed with <TTCLASS="FUNCTION">exec()</TT>, while Python code that is saved in a file can be executed with <TTCLASS="FUNCTION">execfile()</TT>.</P><P>Both <TTCLASS="FUNCTION">eval()</TT> and <TTCLASS="FUNCTION">exec()</TT> can be fed either plain text strings or pre-compiled Python byte code. You can create blobs of byte code with the <TTCLASS="FUNCTION">compile()</TT> function, but you don't have to—it is simply a little more efficient to use bytecode if you execute the same code more than once. The <TTCLASS="FUNCTION">evalfile()</TT> function reads in a file and executes the contents, which must be plain text. You cannot feed <TTCLASS="FUNCTION">execfile</TT> compiled Python byte code.</P><P>Please note that <TTCLASS="FUNCTION">eval()</TT>, <TTCLASS="FUNCTION">exec()</TT>, <TTCLASS="FUNCTION">execfile()</TT> and <TTCLASS="FUNCTION">compile()</TT> are the real ginger: this is what your Python interpreter uses to execute your code.</P><P>The mere ability to execute random bits of code is quite powerful in itself, but code only becomes truly useful if it no longer exists in a void, but can call other, pre-existing bits of code.</P><P>The code we execute with <TTCLASS="FUNCTION">eval()</TT>, <TTCLASS="FUNCTION">exec()</TT> and <TTCLASS="FUNCTION">execfile()</TT> should be brought into relation with the other Python modules that exist in the library, and with the code of our application. Not only that, but preferably also with the <SPAN><ICLASS="EMPHASIS">state</I></SPAN>, that is, the variables and objects, of the application that asks <TTCLASS="FUNCTION">eval()</TT>, <TTCLASS="FUNCTION">exec()</TT> and <TTCLASS="FUNCTION">execfile()</TT> to execute the code.</P><P>To that end, <TTCLASS="FUNCTION">eval()</TT>, <TTCLASS="FUNCTION">exec()</TT> and <TTCLASS="FUNCTION">execfile()</TT> take two parameters. The first, <TTCLASS="VARNAME">globals</TT>, is a dictionary that represents the <SPAN><ICLASS="EMPHASIS">global</I></SPAN> namespace. You can retrieve the global namespace of your application with the function <TTCLASS="FUNCTION">globals()</TT>. The global namespace contains all imported classes, built-in functions and all global variables, but you can also construct a restricted global environment dictionary yourself.</P><P>The second argument, <TTCLASS="VARNAME">locals</TT>, is a dictionary that represents the <SPAN><ICLASS="EMPHASIS">local</I></SPAN> namespace. You can retrieve it with <TTCLASS="FUNCTION">locals()</TT>. The <TTCLASS="VARNAME">locals</TT> dictionary contains whatever names are local to the function your application is currently in. You can also create a restricted (or expanded) <TTCLASS="VARNAME">locals</TT> dictionary yourself.</P><DIVCLASS="WARNING"><P></P><TABLECLASS="WARNING"BORDER="1"WIDTH="100%"><TR><TDALIGN="CENTER"><B>Warning</B></TD></TR><TR><TDALIGN="LEFT"><P>If you mess about with the globals and locals dictionary, be prepared to encounter what the Python Language Reference calls "undefined behavior". For instance, if you execute a bit of code with an empty locals dictionary, you cannot add new names to the namespace. This means that import won't work, for instance, or even variable assignments. Generally speaking, it is best to simply pass the globals dictionary, which means that the locals dictionary used by the executed code will be a copy of the globals dictionary.</P></TD></TR></TABLE></DIV><P>Let's compare these locals and globals from an interactive Python session:</P><PRECLASS="SCREEN">Python 2.0 (#1, Mar 1 2001, 02:42:21)[GCC 2.95.2 19991024 (release)] on linux2Type "copyright", "credits" or "license" for more information.>>> globals(){'__doc__': None, '__name__': '__main__', '__builtins__': <module '__builtin__' (built-in)>}>>> def f():... a=1... print "locals: ", locals()...>>> globals(){'f': <function f at 0x8124a94>, '__doc__': None, '__name__': '__main__', '__builtins__': <module '__builtin__' (built-in)>}>>> f()locals: {'a': 1}>>> </PRE><P>First, we take a look at the contents of the <TTCLASS="VARNAME">globals</TT> dictionary when Python is first started. Then, we define a simple function <TTCLASS="FUNCTION">f</TT>, that creates a variable <TTCLASS="VARNAME">a</TT>, which contains the value 1 and which prints the <TTCLASS="VARNAME">locals</TT> dictionary. Retrieving the value of <TTCLASS="VARNAME">globals</TT> shows that <TTCLASS="FUNCTION">f</TT> is now part of <TTCLASS="VARNAME">globals</TT>. Running <TTCLASS="FUNCTION">f</TT> shows that <TTCLASS="VARNAME">a</TT> is the only member of
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -