|
This appendix provides tips for usage and pointers to useful online resources for developers using Wing IDE.
Archaeopteryx Software provides a number of support resources free of charge.
All of these are available on the web at http://wingide.com/support
.
http://wingide.com/announcelist
.
The Python Language Reference, maintained by the developers of Python,
is available online at www.python.org
or from the Help menu in
Wing IDE.
This reference manual contains the following parts:
This section describes some useful tools that are available to Python programmers but that have not yet been integrated into the Wing's graphical user interface.
Performance profiling is supported by the Python profile
and
pstats
modules.
To create a profile file named profile.tmp
for invocation of
a function main()
you would include the following code
in your application:
import profile profile.run('import mymodule; mymodule.main()', 'profile.tmp')
This will accumulate profile data while running the function main()
in module mymodule
. Note that importing and fully specifying
the module scope is important if you plan to run the profiler under
the Wing debugger. The profiler makes assumptions about scope that
are violated by the debugger so just specifying profile.run('main()', 'profile.tmp')
will not work.
Subsequently, the pstats
module is used to inspect the contents of
the profiler's output file. For example, the following command would
sort the file by cumulative time spent in each function, and then
print out the top 10 compute-intensive calls:
import pstats p = pstats.Stats('profile.tmp') p.sort_stats('cumulative').print_stats(10)
Detailed documentation for profiling is available in the Python Library Reference under The Python Profiler.
Because Python versions 2.0 and later contain code to detect and break object reference cycles, you may not need to worry about cyclical references unless you are using Python 1.5.2.
A common problem in reference counted garbage-collected languages like Python is memory leakage due to cyclical object references. This occurs in cases where an object A has a reference to another object B that has a reference back to object A. The interpreter fails to discard memory held by these objects even if they become unused by the program because a non-zero reference count exists as a result of the cycle.
Cycles may be much longer than just two objects, for example
A -> B -> C -> D -> A
would result in failure to discard objects
A through D.
In these cases, a long-running program will eventually run out of memory as more and more objects are left intact because of their participation in object reference cycles.
A Python module called Cyclops is available for monitoring your program as it runs, to determine when cyclical memory references are preventing the Python interpreter from discarding unused objects.
This module can be used to print information on existing cycles at any time, including at time of program exit.
The following function might be used to invoke a function called main
and then output cycle information for modules and functions upon exit:
#------------------------------------ def RunWithCyclops(): """Run the main program under Cyclops. Require Cyclops.py found at http://www.python.org/ftp/python/contrib/System/Cyclops.py."""from cyclops import Cyclops import types
def mod_refs(x): return x.__dict__.values()
def mod_tag(x, i): return "." + x.__dict__.keys()[i]
def func_refs(x): return x.func_globals, x.func_defaults
def func_tag(x, i): return (".func_globals", ".func_defaults")[i]
def instance_filter(cycle): for obj, index in cycle: if type(obj) is types.InstanceType: return 1 return 0
z = Cyclops.CycleFinder() z.chase_type(types.ModuleType, mod_refs, mod_tag) z.chase_type(types.FunctionType, func_refs, func_tag)
z.run(main) z.find_cycles() z.show_stats() z.show_cycles()
Once cycles are found, the most effective method for fixing the resulting
memory leaks is to introduce a destroy
function that manually
clears references that are causing a cycle (for example, by setting them to
None
or by calling the clear()
method on Python dictionaries
or sequences.
If a cycle is broken at a single point in this way, all objects in the cycle will subsequently be freed. For this reason, busting cycles tends to be relatively easy.
For more information on using Cyclops, please refer to documentation within
the copy located in WINGHOME/cyclops
.
Gdb can be used as a tool to aid in debugging C/C++ extension modules written for Python, although doing so can be a bit tricky and prone to problems. The following text contains hints to make this easier.
Note that this section assumes you are already familiar with gdb; for more information on gdb commands, please refer to the gdb documentation.
The first step in debugging C/C++ modules with gdb is to make
sure that you are using a version of Python
that was compiled with debug symbols. To do this, you need a source
distribution of Python and you need to configure the distribution as
described in the accompanying README
file.
In most cases, this can be done as follows: (1) Type ./configure
, (2) type make OPT=-g
or edit the Makefile so OPT=-g
, (3) type make
, and (4) once
the build is complete, install it with make install
(but see
the README first if you don't want to install into /usr/local/lib/python
).
If you are building an extension module that you are compiling into the Python interpreter, you can now just run Python within gdb, set a breakpoint at the desired location in your extension module, and execute your Python test program.
In most cases, however, the extension module is not compiled into
Python but is instead loaded dynamically at runtime. In order to get
your extension module to load, it must be on the PYTHONPATH
or within the same directory where the module is import
-ed into
Python source.
Gdb additionally requires setting LD_LIBRARY_PATH
to include the
directory where the dynamically loaded module is located. A common
problem in doing this is that gdb will reread .cshrc
each time
that it runs, so setting LD_LIBRARY_PATH
before invoking gdb
has no effect if you also set LD_LIBRARY_PATH
in .cshrc
.
To work around this, set LD_LIBRARY_PATH
in .profile
instead. This file is read only once at login time.
Then start Python as follows:
myhost> gdb (gdb) file python (gdb) run yourprogram.py yourargs
Note that breakpoints in a shared library cannot be set until after
the shared library is loaded. If running your program triggers
loading of your extension module library, you can use ^C^C
to interrupt the debug program, set breakpoints, and then continue.
Otherwise, you must continue running your program until the extension
module is loaded. When in doubt, add a print
statement at point of
import, or you can set a breakpoint at PyImport_AddModule
(this
can be set after file python
and before running since this
call is not in a shared library).
Unfortunately, even if you take all of the above steps, gdb will often get confused if you load and unload shared libraries repeatedly during a single debug session. You can usually re-run Python 5-10 times but subsequently may see crashing, failure to stop at breakpoints, or other odd behaviors. When this occurs, there is no alternative but to exit and restart gdb.
Finally a hint for viewing Python data from the C/C++ side when using
gdb. The following gdb command will print out the contents of a
PyObject *
called obj
as if you had issued the command
print obj
from within the Python language:
(gdb) p PyObject_Print (obj, stderr, 0)
The source code for Wing IDE is available to all users that have a permanent (non-evaluation) license to Wing IDE Standard or higher product level. This section contains information that may be useful to those wanting to delve into the source code to make changes or add custom features.
Before getting started, you should download and install the source distributions, as described in section 1.9.
Once the source is installed, see the document
build-files/README.txt
for build instructions.
If you have problems getting set up for source development, please
send email to support@wingide.com
.
The source code, relative to the top level of the Wing IDE installation, is organized into three major groups of functionality, according to its origin and the distribution licenses that apply to the code:
src
directory. This is
the proprietary code to which you have certain rights if you own a license, but
which you may not redistribute.opensource
contains the portions of the IDE
that were written at Archaeopteryx Software and have been released
under an open source license.external
directory contains additional open source items used
within the IDE but written and maintained outside of Archaeopteryx
Software Inc. Some of these contain substantial modifications that may
not yet be included in the primary distributions of these tools.
Distributed among the above directories are the following major sub-systems of the IDE:
src.pysource
and opensource.parsetools
).opensource.pyscintilla
and external.scintilla
to do most of
its work.opensource.parsetools
.external.scintilla
source code editor module.pygtk-0.6.5
,
which is a Python language wrapper for the gtk
GUI development library.
Throughout the source, Python documentation strings and comments are used to describe the code. As a result, most documentation is located within the code itself.
Each IDE module also has a README
file containing at least some
text identifying the module. This may also contain high level documentation
for the module's source, so it's a good place to start when inspecting the
code.
The top-level docstring (at start of each Python file) contains a CVS logging area, which lists all recent revision comments for that file.
Three techniques are used to build names for language constructs in the Wing IDE source code: (1) leading underscores indicate the public, semi-private, and private nature of the construct, (2) prefix letters are used to indicate the type of some constructs, and (3) capitalization is used to indicate the type of some constructs. This naming style is used with all Python language constructs, including classes, functions, methods, variables, attributes, and in some cases module names.
The presence and number of underscores before construct names is used to indicate the scope of access intended for that construct.
CallMe()
) are used for publically
accessible classes, methods, functions, or attributes. These may be
accessed from anywhere.
_DoSomething()
) is used to indicate that
a construct is semi-private, for access only from within the construct's scope and
related scopes (such as in sub-classes, or other classes that are part
of a logical sub-system).
__MyMethod()
) indicates that a construct
is private. For object attributes, Python will enforce local-only
access of these values by making them invisible from subclasses or outside
of the body of the class.
A prefix-based naming convention is also applied to some language constructs, as follows:
Capitalization of letters within construct names is also standardized:
XxxXxxx
are used for classes, methods, instance
attributes, functions, and constants.xxx_xxx
are used for parameters, locals, module names,
and disk directories.
Underscoring, prefixing, and capitalization are combined as appropriate
for all constructs, to build names like _CMyClass
(a semi-private class),
kAValue
(a public constant), and __fCount
(a private instance attribute).