![]() |
|
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)