import symbol as stdlib_symbol in __init__.py

18 views
Skip to first unread message

Aaron S. Meurer

unread,
Dec 21, 2010, 3:54:58 PM12/21/10
to sy...@googlegroups.com
Why is this line

import symbol as stdlib_symbol

in the main sympy/__init__.py? If I comment it out, there are some test failures, but it seems that wherever this is used it should be imported there (there is no reason that it should be imported into the main namespace). By the way, the symbol module is "Non-terminal symbols of Python grammar (from "graminit.h")."

Aaron Meurer

Ondrej Certik

unread,
Dec 21, 2010, 11:31:17 PM12/21/10
to sy...@googlegroups.com

I think that the problem is that it needs to be imported in
sympy/core, and there is already a file called symbol.py, thus there
is no way to import the stdlib symbol. Thus we need to import it one
level up.

Ondrej

Aaron S. Meurer

unread,
Dec 28, 2010, 12:46:21 AM12/28/10
to sy...@googlegroups.com
Well, it's a problem, because we have stdlib_symbol imported into the namespace with from sympy import *. I wonder if this can be fixed by manipulating sys.modules?

Aaron Meurer

> —

Aaron S. Meurer

unread,
Dec 28, 2010, 4:30:30 PM12/28/10
to Aaron S. Meurer, sy...@googlegroups.com
This *seems* to fix it. The only failure when that import is removed is test_sympify in Python 2.4 and Python 2.5, and it still passes after this diff is applied. The idea is that once you import a module, it is put in sys.modules, even if you immediately delete the module from the namespace after you import it. I don't know how supported this behavior is, though. It seems rather hackish to me.

diff --git a/sympy/__init__.py b/sympy/__init__.py
index 60da6e1..bbc9654 100644
--- a/sympy/__init__.py
+++ b/sympy/__init__.py
@@ -19,6 +19,7 @@ def __sympy_debug():
SYMPY_DEBUG = __sympy_debug()

import symbol as stdlib_symbol
+del stdlib_symbol
from sympy.core import *
from assumptions import *
from polys import *
diff --git a/sympy/core/ast_parser_python24.py b/sympy/core/ast_parser_python24.py
index ed7e41b..1e21d62 100644
--- a/sympy/core/ast_parser_python24.py
+++ b/sympy/core/ast_parser_python24.py
@@ -4,6 +4,7 @@
from compiler.ast import CallFunc, Name, Const
from compiler.pycodegen import ExpressionCodeGenerator
import re
+import sys

from basic import Basic
from symbol import Symbol
@@ -52,7 +53,7 @@ def atom_name(self, nodelist):

def lambdef(self, nodelist):
#this is python stdlib symbol, not SymPy symbol:
- from sympy import stdlib_symbol
+ stdlib_symbol = sys.modules['symbol']
if nodelist[2][0] == stdlib_symbol.varargslist:
names, defaults, flags = self.com_arglist(nodelist[2][1:])
else:

Aaron Meurer

Aaron S. Meurer

unread,
Dec 28, 2010, 5:28:56 PM12/28/10
to Aaron S. Meurer, sy...@googlegroups.com
I just had a conversation on #python about this. After a bit of talk about "from __future__ import absolute_import", which doesn't work in Python 2.4 and would require us changing all of our non-absolute imports everywhere (the person I talked with said we would pretty much have to use it everywhere in SymPy), explicit relative imports (also not supported in Python 2.4, but supported without __future__ in Python 2.5+), and renaming symbol.py (which would also be a lot of work), I figured out that the solution is much simpler than that. We just need to move ast_parser_python24.py, which is the only file that uses this stdlib_symbol, to a separate directory from sympy/core.

So I propose that we move that file, as well as ast_parser.py and sympify.py, to sympy/parsing. If there are no objections, I will create a patch for this.

Aaron Meurer

Robert Kern

unread,
Dec 28, 2010, 5:56:00 PM12/28/10
to sy...@googlegroups.com
On Tue, Dec 28, 2010 at 17:28, Aaron S. Meurer <asme...@gmail.com> wrote:
> I just had a conversation on #python about this.  After a bit of talk about "from __future__ import absolute_import", which doesn't work in Python 2.4 and would require us changing all of our non-absolute imports everywhere (the person I talked with said we would pretty much have to use it everywhere in SymPy),

I don't think this is not true. You would just need to do it in the
one module that needs the stdlib's symbol module.

> explicit relative imports (also not supported in Python 2.4, but supported without __future__ in Python 2.5+), and renaming symbol.py (which would also be a lot of work), I figured out that the solution is much simpler than that.  We just need to move ast_parser_python24.py, which is the only file that uses this stdlib_symbol, to a separate directory from sympy/core.

This is probably the best idea.

--
Robert Kern

"I have come to believe that the whole world is an enigma, a harmless
enigma that is made terrible by our own mad attempt to interpret it as
though it had an underlying truth."
  -- Umberto Eco

Ondrej Certik

unread,
Dec 29, 2010, 3:14:11 AM12/29/10
to sy...@googlegroups.com
On Tue, Dec 28, 2010 at 11:56 PM, Robert Kern <rober...@gmail.com> wrote:
> On Tue, Dec 28, 2010 at 17:28, Aaron S. Meurer <asme...@gmail.com> wrote:
>> I just had a conversation on #python about this.  After a bit of talk about "from __future__ import absolute_import", which doesn't work in Python 2.4 and would require us changing all of our non-absolute imports everywhere (the person I talked with said we would pretty much have to use it everywhere in SymPy),
>
> I don't think this is not true. You would just need to do it in the
> one module that needs the stdlib's symbol module.
>
>> explicit relative imports (also not supported in Python 2.4, but supported without __future__ in Python 2.5+), and renaming symbol.py (which would also be a lot of work), I figured out that the solution is much simpler than that.  We just need to move ast_parser_python24.py, which is the only file that uses this stdlib_symbol, to a separate directory from sympy/core.
>
> This is probably the best idea.

Yes, let's do that.

Ondrej

Aaron S. Meurer

unread,
Dec 29, 2010, 10:36:17 PM12/29/10
to sy...@googlegroups.com
OK. I have made the change. See https://github.com/sympy/sympy/pull/58.

Some questions/concerns:

- What is the purpose of the bottom imports (imports at the bottom of the file) in some of the sympy/core files? I moved the from sympify imports from the bottom to the top, but left the rest alone because I didn't know why they were there.

- I have added SympifyError to the list of things imported with from sympy import *. Is this a good idea? It wasn't imported before, but it seems to me that you should have these errors in the namespace so that you can catch them.

- Can/should I add a test for the fact that stdlib_symbol is no longer in the main namespace? This isn't the first time we have had junk make its way into the main namespace (see http://code.google.com/p/sympy/issues/detail?id=1454).

- I inserted from sympy.parsing import * in a place where it seemed to work in the main __init__.py, but I don't know if this order matters for things other than the order that it has to work in.

- Why do we import init_session and init_printing into the global namespace?

Aaron Meurer

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

Ondrej Certik

unread,
Dec 30, 2010, 2:42:44 AM12/30/10
to sy...@googlegroups.com
On Thu, Dec 30, 2010 at 4:36 AM, Aaron S. Meurer <asme...@gmail.com> wrote:
> OK.  I have made the change.  See https://github.com/sympy/sympy/pull/58.
>
> Some questions/concerns:
>
> - What is the purpose of the bottom imports (imports at the bottom of the file) in some of the sympy/core files?  I moved the from sympify imports from the bottom to the top, but left the rest alone because I didn't know why they were there.

This is to avoid circular dependencies. Try to move it to top and run
tests and you'll see.

>
> - I have added SympifyError to the list of things imported with from sympy import *.  Is this a good idea?  It wasn't imported before, but it seems to me that you should have these errors in the namespace so that you can catch them.
>
> - Can/should I add a test for the fact that stdlib_symbol is no longer in the main namespace?  This isn't the first time we have had junk make its way into the main namespace (see http://code.google.com/p/sympy/issues/detail?id=1454).

I don't have an opinion. If you think it's worthy, then let's do it.

>
> - I inserted from sympy.parsing import * in a place where it seemed to work in the main __init__.py, but I don't know if this order matters for things other than the order that it has to work in.
>
> - Why do we import init_session and init_printing into the global namespace?

I think so that one can initialize such sessions in raw Python
interpreter. If you think these things don't belong there, feel free
not to import them any more.

Ondrej

Aaron S. Meurer

unread,
Dec 30, 2010, 2:49:58 AM12/30/10
to sy...@googlegroups.com

On Dec 30, 2010, at 12:42 AM, Ondrej Certik wrote:

> On Thu, Dec 30, 2010 at 4:36 AM, Aaron S. Meurer <asme...@gmail.com> wrote:
>> OK. I have made the change. See https://github.com/sympy/sympy/pull/58.
>>
>> Some questions/concerns:
>>
>> - What is the purpose of the bottom imports (imports at the bottom of the file) in some of the sympy/core files? I moved the from sympify imports from the bottom to the top, but left the rest alone because I didn't know why they were there.
>
> This is to avoid circular dependencies. Try to move it to top and run
> tests and you'll see.

Right.

>
>>
>> - I have added SympifyError to the list of things imported with from sympy import *. Is this a good idea? It wasn't imported before, but it seems to me that you should have these errors in the namespace so that you can catch them.
>>
>> - Can/should I add a test for the fact that stdlib_symbol is no longer in the main namespace? This isn't the first time we have had junk make its way into the main namespace (see http://code.google.com/p/sympy/issues/detail?id=1454).
>
> I don't have an opinion. If you think it's worthy, then let's do it.

How do others feel about testing the global namespace? We would have to test sympy.__dict__.

>
>>
>> - I inserted from sympy.parsing import * in a place where it seemed to work in the main __init__.py, but I don't know if this order matters for things other than the order that it has to work in.
>>
>> - Why do we import init_session and init_printing into the global namespace?
>
> I think so that one can initialize such sessions in raw Python
> interpreter. If you think these things don't belong there, feel free
> not to import them any more.

Is it different from running "from sympy.interactive import *"? Again, how do others feel about this? I myself am just getting tired of the slow import time and want to remove superfluous things from SymPy's __init__.py's.

Aaron Meurer


>
> Ondrej

Ondrej Certik

unread,
Dec 30, 2010, 2:57:41 AM12/30/10
to sy...@googlegroups.com

I forgot about the "from sympy.interactive import *". Yes, let's move
it out of the __init__.py's.

Ondrej

Vinzent Steinberg

unread,
Dec 30, 2010, 6:37:13 AM12/30/10
to sympy
On 30 Dez., 08:57, Ondrej Certik <ond...@certik.cz> wrote:
> I forgot about the "from sympy.interactive import *". Yes, let's move
> it out of the __init__.py's.

I agree, it makes more sense there.

Vinzent

Mateusz Paprocki

unread,
Dec 30, 2010, 7:17:18 AM12/30/10
to sy...@googlegroups.com
Hi,

For one user this is useless for the other it's useful, so this way we may have hard time removing "superfluous" imports. But lets consider the use cases. We have interactive sessions, where we would like to have all useful stuff ready to use and non-interactive where we can afford writing explicit or semi-explicit imports (from sympy.core.add import Add vs. from sympy.core import Add) to import this useful stuff. Every user has he's own definition of "useful stuff". Lets focus on interactive sessions. Personally, I use IPython in 99.9% of cases and I hate importing stuff manually and I expect all the common stuff + stuff related to my work already imported at interpreter start, but I also don't like slow import times in both interactive and non-interactive sessions.

Lets assume we reduce from sympy import * to the bare minimum. Then we should create another entry point, say sympy.all (or something), which would allow us to write from sympy.all import * and get the current behaviour of from sympy import *. Then we can add a switch to isympy, e.g. --all, which would import from sympy.all on interpreter startup (or a configuration file for sympy, which we should add sooner or later). I'm not sure about this, but in IPython we could maintain a list of modules' imports and we may use some kind of hook to catch NameErrors and ask the user what to do: (1) do nothing, (2) import the name or (3) import everything from the module, or choose from (1-3) automatically based on local sympy's configuration (a command-line switch or configuration file).

Implementing at least some of the above options, should give us short startup times and make interactive usage of sympy less painful. 
 

Aaron Meurer


>
> Ondrej

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


Mateusz

Aaron S. Meurer

unread,
Dec 30, 2010, 4:22:50 PM12/30/10
to sy...@googlegroups.com
So it's basically lazy importing, right?  This is an interesting idea.  I wonder, though, if it will make a difference.  I noticed when I was fixing the import statements for this issue that because of dependencies, by the time that it got past importing the core and importing the polys, almost everything else had already been executed.  For example, the polys use factorial, which causes the functions to be compiled.  I guess it depends on what takes a long time when importing: the compiling/running of module files, or moving those files into the namespace.  Of course, we know that we can remove things like geometry and physics, which are not used by any other module.  

But anyway, when I said "superfluous," I was specifically referring to init_session, which is the exact same as from sympy.interactive import *.  Actually, it is worse, because init_session being imported from "from sympy import *" implies that you have already imported everything, and so all it is doing then is setting up the printer and creating the x, y, z symbols.  

Aaron Meurer

Mateusz Paprocki

unread,
Dec 30, 2010, 5:06:10 PM12/30/10
to sy...@googlegroups.com
Hi,

I see. So, I'm definitely +1 for removing interactive from __init__.
 
 

Aaron Meurer

 

Aaron Meurer


>
> Ondrej

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


Mateusz

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

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

Mateusz
Reply all
Reply to author
Forward
0 new messages