Any fix that I can think up for this is somewhat fragile, so unless
someone can come up with something that clearly won't break anything,
I think I am going to leave this alone for now.  I do think we should
try to do something about it, but doing it right before a release is
probably a bad idea.

With that being said, my ideas so far are:

- Wrap the imports in plot.py (and elsewhere) with something like

global np, matplotlib
def _import_np_matplotlib():
    global np, matplotlib
    np = import_module('numpy')
    matplotlib = import_module('matplotlib')

The issue here is that _import_np_matplotlib() has to be called before
np or matplotlib can be used (obviously), and for it to have any
effect, it must be inside a function call (not inside a class
definition).  So I can put it at the top of the user-level functions
like plot(), but if someone tries to use the internal classes
directly, it won't work.

- My other idea was to make import_module() return a lazy object,
which acts like the module, but doesn't actually import the module
until it is used.  This works, but the problem is that to work
completely transparently, it has to import the module basically as
soon as it is touched.  This means that the current code in plot.py,
which looks something like

matplotlib = import_module("matplotlib")
if matplotlib:
    plt = matplotlib.pyplot
    # etc.

still imports matplotlib right away, because the "if matplotlib" line
requires matplotlib to be imported (it's the only way to know if it is
installed).  This particular case might be fixable with some more code
refactoring, but it just shows how fragile this approach is.  If you
really want the module to only be imported when it is used, and not at
sympy import time, you have to be very careful about how you structure
the code.  The only way to really know if you've done it right is to
check if importing sympy also imports matplotlib (by checking
sys.modules).  And as this example shows, it's not always easy to
structure the code in this way.

So if anyone has some ideas, I'd love to hear them. I know this
touches on some pretty advanced Python stuff, but even if you don't
know how stuff works but you have an abstract idea, I'd love to hear
it.  If you are interested, I can push up my code with the lazy import
object.

(By the way, another "fix" would be to not import the plotting module
by default. This I would rather not do)

Aaron Meurer

On Sat, Sep 22, 2012 at 8:13 PM, Aaron Meurer <[email protected]> wrote:
> I bisected it to this commit:
>
> commit 847bdfcb2c836d0e8853a9b985ef2bf88a925dd4
> Author: Stefan Krastanov <[email protected]>
> Date:   Tue Nov 15 19:54:25 2011 +0100
>
>     Adding plot function (not implemented)
>
>     The docstring for the plot function is ready. The function itself is not
>     ready. It just calls Plot with the same arguments.
>
>     Also now the default between a contour plot and a 3d plot is the 3d plot.
>
>     Also fixed some comments.
>
> which is the first commit where the new plotting module is imported
> with "import sympy".  So I think the issue is that it imports numpy
> and matplotlib.  We should restructure the module to only import those
> modules if the plotting module is used.  Otherwise, we are making
> importing sympy too slow for the majority of users (who also have
> numpy and matplotlib installed).
>
> Aaron Meurer
>
> On Sat, Sep 22, 2012 at 7:41 PM, Aaron Meurer <[email protected]> wrote:
>> I was going through https://github.com/sympy/sympy/wiki/new-release in
>> preparation to cut the release candidate, when I get to the "speed of
>> import" section.  I compared the test_import tool against SymPy 0.7.1
>> and the 0.7.2 branch, and there appears to be a significant slow-down
>> (by almost 4x).
>>
>> Can other people reproduce this?  If so, we need to figure out if it
>> is possible to bring this back down again.
>>
>> sympy(sympy-0.7.1)$%$./bin/test_import
>> Note: the first run (warm up) was not included in the average + std dev
>> All runs (including warm up):
>> [0.632580041885, 0.142980098724, 0.144616127014, 0.18177986145,
>> 0.153340816498, 0.146248817444, 0.152235031128, 0.147120952606,
>> 0.149618864059, 0.147889852524, 0.146507978439, 0.146991014481,
>> 0.148049116135, 0.149016857147, 0.146153926849, 0.149012088776,
>> 0.146345853806, 0.145620822906, 0.156076908112, 0.146780014038,
>> 0.148214817047, 0.146635055542, 0.148654937744, 0.14654302597,
>> 0.146838188171, 0.14808511734, 0.147293806076, 0.148097991943,
>> 0.149609804153, 0.148839950562, 0.147723913193, 0.146723985672,
>> 0.151859045029, 0.147171974182, 0.148344039917, 0.14845085144,
>> 0.147562980652, 0.151570081711, 0.200988054276, 0.150926113129,
>> 0.152683973312, 0.149338960648, 0.148150920868, 0.149286031723,
>> 0.146691083908, 0.147687911987, 0.145917892456, 0.14581489563,
>> 0.150799036026, 0.147582054138, 0.145636796951]
>> Number of tests: 50
>> The speed of "import sympy" is: 0.149922 +- 0.008985
>> sympy(sympy-0.7.1)$%$git co 0.7.2
>> Previous HEAD position was 556fe55... SymPy 0.7.1 release
>> Switched to branch '0.7.2'
>> sympy0.7.2$%=$./bin/test_import
>> Note: the first run (warm up) was not included in the average + std dev
>> All runs (including warm up):
>> [1.01710915565, 0.398802042007, 0.396264076233, 0.397413015366,
>> 0.391931056976, 0.403698921204, 0.3991959095, 0.393259048462,
>> 0.411875009537, 0.397119045258, 0.414400100708, 0.465793132782,
>> 0.43417596817, 0.443454027176, 0.417393922806, 0.453384876251,
>> 0.400901079178, 0.393971920013, 0.39364695549, 0.393153905869,
>> 0.39675116539, 0.395659923553, 0.400503873825, 0.399799823761,
>> 0.406329870224, 0.393779039383, 0.400959968567, 0.392513036728,
>> 0.396237850189, 0.392780065536, 0.396032810211, 0.391910076141,
>> 0.396354913712, 0.393106937408, 0.514472961426, 0.428894042969,
>> 0.418586015701, 0.423231840134, 0.418197154999, 0.420174837112,
>> 0.414786100388, 0.420045852661, 0.438434839249, 0.424329996109,
>> 0.426602125168, 0.424081087112, 0.420931816101, 0.427915096283,
>> 0.418045043945, 0.421542882919, 0.424115896225]
>> Number of tests: 50
>> The speed of "import sympy" is: 0.412739 +- 0.022607
>>
>> Aaron Meurer

-- 
You received this message because you are subscribed to the Google Groups 
"sympy" group.
To post to this group, send email to [email protected].
To unsubscribe from this group, send email to 
[email protected].
For more options, visit this group at 
http://groups.google.com/group/sympy?hl=en.

Reply via email to