Best way to import Sympy

88 views
Skip to first unread message

Javier Arantegui

unread,
Jun 29, 2020, 10:54:31 AM6/29/20
to sy...@googlegroups.com
Hi!

Most probably, this is a silly question...

What is the best way to import Sympy?

I usually use:

from sympy import *

I know that using a wild import should be avoided. Is this a better way:

import sympy as sp

Best regards,

Javier

Oscar Benjamin

unread,
Jun 29, 2020, 12:15:35 PM6/29/20
to sympy
On Mon, 29 Jun 2020 at 15:54, Javier Arantegui
<javier.a...@gmail.com> wrote:
>
> Hi!

Hi Javier,

> Most probably, this is a silly question...

I don't think it's a silly question

> What is the best way to import Sympy?
>
> I usually use:
>
> from sympy import *
>
> I know that using a wild import should be avoided. Is this a better way:
>
> import sympy as sp

This is more of a general Python question than a sympy-specific
question. My answer is that it really depends on the context but my
rules of thumb is that star-imports are fine if you're writing a
single script that uses a single star-import.

Are you writing a small script to do a short calculation or are you
editing a large codebase with many different modules and internal and
external imports?

In any significant codebase star-import is a bad idea. It makes it
hard to trace the origin of an imported name when looking at the code.
If I'm looking at the code and I see sp.cos then I expect that sp will
be defined or imported somewhere at the top of the file and I can just
go to the first occurrence of it in the file to see where it comes
from. Likewise if you use "from sympy import cos" and I see cos(2) I
expect that cos will be imported at the top and I can search for that.

There have been issues in sympy where __init__.py files used
star-imports making some objects importable by accident. The
conclusion from those examples is that it is bad to use star-imports
when writing modules that other code will import from. Within the
sympy codebase itself most imports are more explicit like

from sympy.polys.polymatrix import PolyMatrix

That's a good practice for internal imports in a large codebase. There
are a few places around the sympy code base where names are imported
from top level sympy like

from sympy import cos

Those are not fine *within* sympy because they lead to circular import
problems. For users of sympy though I think that this would be
considered good practice.

The above is all about large codebases though (e.g. sympy has 750000
lines of code). If you are writing a short script that just uses sympy
to compute something then I don't see anything wrong with using a
star-import for brevity. Of course there's a big range between a
10-line calculation and a 750K-LOC library and you'll have to decide
where your code fits in that range...

Also are you combining sympy with other libraries such as numpy and
are you star-importing from all of them?

Many problems of star-import come from things like multiple star
imports. Both numpy and sympy have a cos function so if you
star-import both modules which one will you get? The two cos functions
are deliberately different so it does matter. Because of that even in
a short script that mixes numpy and sympy I would go with

import sympy as sp
import numpy as np

or perhaps

from sympy import *
import numpy as np

but never

from sympy import *
from numpy import *

Both sympy and numpy have hundreds of names at top-level and many of
them are the same names.

For simple interactive calculations I use isympy which does this when it starts:

>>> from __future__ import division
>>> from sympy import *
>>> x, y, z, t = symbols('x y z t')
>>> k, m, n = symbols('k m n', integer=True)
>>> f, g, h = symbols('f g h', cls=Function)
>>> init_printing()

That saves a bunch of boiler-plate so you can quickly get started.
It's also convenient for pasting examples: I often paste code snippets
to show someone something with the implication that it works in isympy
with the above import and symbols. This is the original purpose of
star-import: to be convenient in an interactive context.

I see lots of examples around where people do different variants like

import sympy; sympy.cos(2)
import sympy as sp; sp.cos(2)
import sympy as sy; sy.cos(2)

and other less common examples. I wonder if it would be worthwhile for
sympy to endorse one of these explicitly in the way that numpy does
with np.

--
Oscar

Jonathan Gutow

unread,
Jun 29, 2020, 2:38:51 PM6/29/20
to sy...@googlegroups.com
+1 for encouraging `import sympy as sp`, when every things are not
simple enough for `from sympy import *`.

Jonathan

On 6/29/20 11:16 AM, Oscar Benjamin wrote:
> CAUTION: This email originated from outside of the organization. Do not click links or open attachments unless you recognize the sender and know the content is safe.
> --
> You received this message because you are subscribed to the Google Groups "sympy" group.
> To unsubscribe from this group and stop receiving emails from it, send an email to sympy+un...@googlegroups.com.
> To view this discussion on the web visit https://nam12.safelinks.protection.outlook.com/?url=https%3A%2F%2Fgroups.google.com%2Fd%2Fmsgid%2Fsympy%2FCAHVvXxRu1Y3CzHJOWJbATOsDvTnY7vZRUb5yYowZvqjQHJqVfw%2540mail.gmail.com&amp;data=02%7C01%7Cgutow%40uwosh.edu%7C49e15f2f542e455d3b3308d81c47a5e9%7C16b8b9f2f7bd431ab739d49428e26316%7C0%7C0%7C637290441336920658&amp;sdata=fXignxLFKK8ek9FnXpEOz%2FJDVjBtsOqDjEB1ymLpsaw%3D&amp;reserved=0.

--
Dr. Jonathan Gutow
Chemistry Department
UW Oshkosh
web: https://uwosh.edu/facstaff/gutow
e-mail: gu...@uwosh.edu
Ph: 920-424-1326

Aaron Meurer

unread,
Jun 29, 2020, 2:56:30 PM6/29/20
to sympy
The sp shorthand is usually used for scipy. I recommend using 'import
sympy as sym' or 'import sympy as sm' (sm is also used by statsmodels
so I would avoid that one if you use that library).

Aaron Meurer
> To view this discussion on the web visit https://groups.google.com/d/msgid/sympy/cc227f60-7e26-c920-df9b-78e84b0c0af6%40uwosh.edu.

David Bailey

unread,
Jun 29, 2020, 4:43:14 PM6/29/20
to sy...@googlegroups.com
On 29/06/2020 17:16, Oscar Benjamin wrote:

In any significant codebase star-import is a bad idea. It makes it
hard to trace the origin of an imported name when looking at the code.
If I'm looking at the code and I see sp.cos then I expect that sp will
be defined or imported somewhere at the top of the file and I can just
go to the first occurrence of it in the file to see where it comes
from. Likewise if you use "from sympy import cos" and I see cos(2) I
expect that cos will be imported at the top and I can search for that.

I feel there are some good reasons to star import SymPy (which is why this subject keeps coming up) these reasons tend to get downplayed. One is the obvious fact that complicated algebraic equations just don't look nice with sp. prefixing functions like cos(). Another is the fact that I would guess many users only intend to use SymPy even though their code is complicated - not really throw away one-off code. Such users are, in effect, using Sympy as an algebra processing system, and are not interested in Python, though they might want to import their own modules that also star imported SymPy.

SymPy's 750000 lines of code is obviously an extreme case.

There also seems to be a certain inconsistency associated with importing SymPy symbols selectively (tested using 1.6):

import sympy
from sympy import integrate
from sympy import sin
x=sympy.symbols('x')

integrate(sin(x),x)

Returns

-cos(x)

I would have expected -sympy.cos(x), and indeed if you subsequently enter cos(x), you get a name error because cos is not defined!


For these reasons, I think it might be worth devising a set of rules that can be followed so as to import SymPy safely as widely as possible. How about:

1)          Only import SymPy  using  * Thus numpy (say) would have to be imported as

import numpy as np and incur the clumsier syntax of np.cos(...)

This is nearly inevitable because you can't end up with two things called cos.

2)         If you are importing other modules that you have written, use exactly the same import commands in all of them.

Struggling as a newcomer with SymPy without importing everything including sympy.abc (and maybe without knowing the Python language) can be extremely frustrating .

David





Nicolas Guarin

unread,
Jun 30, 2020, 11:34:07 AM6/30/20
to sympy
I would recommend use the star import for interactive CAS  work, otherwise I would second Aaron in using

    import sympy as sym

On Monday, June 29, 2020 at 3:43:14 PM UTC-5, David Bailey wrote:
On 29/06/2020 17:16, Oscar Benjamin wrote:

In any significant codebase star-import is a bad idea. It makes it
hard to trace the origin of an imported name when looking at the code.
If I'm looking at the code and I see sp.cos then I expect that sp will
be defined or imported somewhere at the top of the file and I can just
go to the first occurrence of it in the file to see where it comes
from. Likewise if you use "from sympy import cos" and I see cos(2) I
expect that cos will be imported at the top and I can search for that.

I feel there are some good reasons to star import SymPy (which is why this subject keeps coming up) these reasons tend to get downplayed. One is the obvious fact that complicated algebraic equations just don't look nice with sp. prefixing functions like cos(). Another is the fact that I would guess many users only intend to use SymPy even though their code is complicated - not really throw away one-off code. Such users are, in effect, using Sympy as an algebra processing system, and are not interested in Python, though they might want to import their own modules that also star imported SymPy.

SymPy's 750000 lines of code is obviously an extreme case.

There also seems to be a certain inconsistency associated with importing SymPy symbols selectively (tested using 1.6):

import sympy
from sympy import integrate
from sympy import sin
x=sympy.symbols('x')

integrate(sin(x),x)

Returns

-cos(x)

I would have expected -sympy.cos(x), and indeed if you subsequently enter cos(x), you get a name error because cos is not defined!



You can import something like

    from sympy import sin, cos, tan, exp

so you don't have this kind of problem.

Oscar Benjamin

unread,
Jun 30, 2020, 12:06:53 PM6/30/20
to sympy
On Tue, 30 Jun 2020 at 16:34, Nicolas Guarin <nicog...@gmail.com> wrote:
>
> I would recommend use the star import for interactive CAS work, otherwise I would second Aaron in using
>
> import sympy as sym

Okay maybe we should go with this. It's less ambiguous than the other
variants and is potentially more meaningful/recognisable to people who
aren't familiar with the short names of other python libraries and
perhaps to matlab users as well. I guess that the py is sort of
redundant inside a .py file.

If we want to endorse this as the suggested short spelling then we
could start by adding it as a suggestion and discussing other options
like star-import somewhere near the start of the tutorial:
https://docs.sympy.org/latest/tutorial/intro.html#the-power-of-symbolic-computation

We could also add "import sympy as sym" as part of the startup in
isympy. Then examples of code that use that style would work if pasted
in.

I notice that numpy doc examples seem to be written with an implied
"import numpy as np":
https://numpy.org/doc/stable/reference/generated/numpy.sin.html

The tutorial there shows "import numpy as np" as the very first line
of code and then mostly uses np throughout:
https://numpy.org/doc/stable/user/quickstart.html

I don't know if that's something that we should emphasise more
generally in docs. I do often see users on stackoverflow etc mixing up
things like math.sin, numpy.sin and sympy.sin.

Oscar

Jonathan Gutow

unread,
Jun 30, 2020, 2:27:24 PM6/30/20
to sy...@googlegroups.com
+1 to this option. I agree with Oscar, this seems the least ambiguous
and simplest recommendation. I also second Oscar's suggestion that
examples in the tutorial should be modified to reflect this.

On 6/30/20 11:07 AM, Oscar Benjamin wrote:
> I would recommend use the star import for interactive CAS work, otherwise I would second Aaron in using
>
> import sympy as sym

Aaron Meurer

unread,
Jun 30, 2020, 3:02:49 PM6/30/20
to sympy
On Mon, Jun 29, 2020 at 2:43 PM David Bailey <da...@dbailey.co.uk> wrote:
>
> On 29/06/2020 17:16, Oscar Benjamin wrote:
>
>
> In any significant codebase star-import is a bad idea. It makes it
> hard to trace the origin of an imported name when looking at the code.
> If I'm looking at the code and I see sp.cos then I expect that sp will
> be defined or imported somewhere at the top of the file and I can just
> go to the first occurrence of it in the file to see where it comes
> from. Likewise if you use "from sympy import cos" and I see cos(2) I
> expect that cos will be imported at the top and I can search for that.
>
> I feel there are some good reasons to star import SymPy (which is why this subject keeps coming up) these reasons tend to get downplayed. One is the obvious fact that complicated algebraic equations just don't look nice with sp. prefixing functions like cos(). Another is the fact that I would guess many users only intend to use SymPy even though their code is complicated - not really throw away one-off code. Such users are, in effect, using Sympy as an algebra processing system, and are not interested in Python, though they might want to import their own modules that also star imported SymPy.
>
> SymPy's 750000 lines of code is obviously an extreme case.
>
> There also seems to be a certain inconsistency associated with importing SymPy symbols selectively (tested using 1.6):
>
> import sympy
> from sympy import integrate
> from sympy import sin
> x=sympy.symbols('x')
>
> integrate(sin(x),x)
>
> Returns
>
> -cos(x)
>
> I would have expected -sympy.cos(x), and indeed if you subsequently enter cos(x), you get a name error because cos is not defined!

The printer doesn't take into account your namespace. It is
copy-pastable from the point of view of having all the SymPy names
imported. We could add a string printer mode that prefixes all SymPy
names.

>
>
> For these reasons, I think it might be worth devising a set of rules that can be followed so as to import SymPy safely as widely as possible. How about:
>
> 1) Only import SymPy using * Thus numpy (say) would have to be imported as
>
> import numpy as np and incur the clumsier syntax of np.cos(...)
>
> This is nearly inevitable because you can't end up with two things called cos.

If you are writing code in a file, import * should be avoided. This
applies to all modules, not just SymPy. There are many issues with it.

- It makes it hard for both human readers and linters to detect if a
name is undefined or mispelled. For example, pyflakes completely gives
up on trying to find undefined names if there is an import *.
- If you combine multiple import *s, the actual name that gets
imported is whichever was imported last. It can be difficult to tell
this if you don't know for sure *every* name that is included in an
import *.
- If a module isn't careful about defining __all__, import * may
import more than you would expect. SymPy as of recent versions defines
__all__ but it didn't used to. And many other libraries do not. For
example, say a module has "import sys" in its __init__.py and you do
an import * of that module. Then you would get "sys" defined even
though you never ran "import sys". Even worse things are possible here
too, such as an import * overriding a built-in name. SymPy does try to
avoid this, but other packages are not as careful.

import * is just fine for interactive use, although the caveats about
SymPy and NumPy including the same names still apply. The issue is
that for .py files, import * starts to lead to code smells that can
give you issues down the line making the code both harder to read and
maintain. Remember that if you are putting your code in a file, then
your goal is to make that code readable by other people (even if
"other people" just means your future self).

If you don't like using sym.cos and so on everywhere, you can just
import things directly, like

from sympy import cos

That is just fine. If you look at the code in SymPy itself, it uses
this pattern (except it often imports directly from submodules, which
end-users should not do). For example, look at the test_solvers.py
file https://github.com/sympy/sympy/blob/master/sympy/solvers/tests/test_solvers.py.
There are a lot of imports there, but it is not a problem. You could
also use a tool like isort to keep the imports clean and in order.
Also tools like pyflakes make it easy to keep track of which names you
have forgotten to import, or which imports are no longer necessary.

The only issue with doing a direct import like this is that if you are
also using a library like NumPy, you need to be careful because NumPy
also has a cos() function, and it is incompatible with SymPy's. If
your code is primarily SymPy code that uses NumPy only in a small
part, you could do

from sympy import cos, ...
import numpy as np

and use the np.cos prefix in the parts where you need the NumPy
version. It all really depends on what your code is doing and what
will make it the most readable.

Aaron Meurer

>
> 2) If you are importing other modules that you have written, use exactly the same import commands in all of them.
>
> Struggling as a newcomer with SymPy without importing everything including sympy.abc (and maybe without knowing the Python language) can be extremely frustrating .
>
> David
>
>
>
>
>
> --
> You received this message because you are subscribed to the Google Groups "sympy" group.
> To unsubscribe from this group and stop receiving emails from it, send an email to sympy+un...@googlegroups.com.
> To view this discussion on the web visit https://groups.google.com/d/msgid/sympy/b0324ab9-fe2c-e813-9c95-04a0c6864a96%40dbailey.co.uk.

David Bailey

unread,
Jun 30, 2020, 5:53:16 PM6/30/20
to sy...@googlegroups.com
Aaron, thanks for responding to my question in detail.

On 30/06/2020 20:00, Aaron Meurer wrote:

The printer doesn't take into account your namespace. It is
copy-pastable from the point of view of having all the SymPy names
imported. We could add a string printer mode that prefixes all SymPy
names.

Thanks, I wasn't aware that print() works that way.

The problem seems to remain that if you integrate sin(x) you get cos(x), yo get a symbol cos that you didn't anticipate. Maybe integrating sin(x**3) would be a better example, where hypergeometrics and gamma functions suddenly appear in the answer - I mean these will appear without  regard to the selective importing of SymPy. Thus if you copy/paste these into an input, these will generate an undefined name error because they are not prefixed.
If you don't like using sym.cos and so on everywhere, you can just
import things directly, like

from sympy import cos

Precisely - as explained above.

I mean, is copy/paste an unusual thing to use - I would have thought it was completely normal.

I don't know Python anywhere near well enough to figure out if it is possible for print() or something else, like fullprint() to add appropriate prefixes (like sp.) to things (not just every possible prefix) as it outputs them - can it extract enough information to actually do this?

My suggestion to use "from sympy import *" within modules was meant to apply in a situation where you used a collection of modules for various purposes which all imported just SymPy. I can't quite see what the problem is in that case, unless you use Python tools.

Even without using *, it is still possible to accidentally import something from more than one module:

from sympy import sin

from numpy import sin

Indeed if you are going to use numpy in conjunction with sympy, this sort of clash seems quite inevitable unless you make all the numpy symbols work using the np. prefix.

BTW, I really do not wish to be a nuisance, because I do realise what a magnificent facility SymPy represents, and the work that must have gone into it.

David



Aaron Meurer

unread,
Jun 30, 2020, 6:20:38 PM6/30/20
to sympy
On Tue, Jun 30, 2020 at 3:53 PM David Bailey <da...@dbailey.co.uk> wrote:
>
> Aaron, thanks for responding to my question in detail.
>
> On 30/06/2020 20:00, Aaron Meurer wrote:
>
>
> The printer doesn't take into account your namespace. It is
> copy-pastable from the point of view of having all the SymPy names
> imported. We could add a string printer mode that prefixes all SymPy
> names.
>
> Thanks, I wasn't aware that print() works that way.
>
> The problem seems to remain that if you integrate sin(x) you get cos(x), yo get a symbol cos that you didn't anticipate. Maybe integrating sin(x**3) would be a better example, where hypergeometrics and gamma functions suddenly appear in the answer - I mean these will appear without regard to the selective importing of SymPy. Thus if you copy/paste these into an input, these will generate an undefined name error because they are not prefixed.
>
> If you don't like using sym.cos and so on everywhere, you can just
> import things directly, like
>
> from sympy import cos
>
> Precisely - as explained above.
>
> I mean, is copy/paste an unusual thing to use - I would have thought it was completely normal.
>
> I don't know Python anywhere near well enough to figure out if it is possible for print() or something else, like fullprint() to add appropriate prefixes (like sp.) to things (not just every possible prefix) as it outputs them - can it extract enough information to actually do this?

I mean we could make something like

>>> sstr(sin(x), prefix='sym')
'sym.sin(x)'

work. I am not suggesting the printer would automatically deduce the
prefix from your environment.

>
> My suggestion to use "from sympy import *" within modules was meant to apply in a situation where you used a collection of modules for various purposes which all imported just SymPy. I can't quite see what the problem is in that case, unless you use Python tools.
>
> Even without using *, it is still possible to accidentally import something from more than one module:
>
> from sympy import sin
>
> from numpy import sin

The difference is that cases like this can easily be spotted by tools
like pyflakes, or even by hand. On the other hand if you have

from sympy import *
from numpy import *

it is not obvious that those overwrite names from each other, unless
you happen to know that numpy and sympy include some of the same
names. "from sympy import *' imports over 900 names and "from numpy
import *" imports over 500. No one should be expected to know what is
happening there. And automated tools like pyflakes won't help you here
either since they basically stop working in the presence of "import
*".

The 'import sin' example will also *only* affect 'sin'. The 'import *'
version will clash names that you might not even be using yet, causing
bugs not just in your current code but in future code as well.

>
> Indeed if you are going to use numpy in conjunction with sympy, this sort of clash seems quite inevitable unless you make all the numpy symbols work using the np. prefix.

You have two options. The correct thing to do depends on what your
code looks like, to what degree you are using numpy vs. sympy, etc.

- Prefix at least one of the names, or both, like np.sin or sym.sin
- Make use of namespaces. Each function can have its own imports
inside of it, which won't affect other functions, like

def sympy_code():
from sympy import sin, ...

def numpy_code():
from numpy import sin, ...

However, this second option only really works if your code happens to
be organized in a specific way that SymPy and NumPy are completely
separated. The prefixed approach always works, which is why it is
recommended.

>
> BTW, I really do not wish to be a nuisance, because I do realise what a magnificent facility SymPy represents, and the work that must have gone into it.

It's not a nuisance. I think it's important for people to understand
why 'import *' is a code smell, and is only really good for
convenience in interactive situations, where code is typically only
executed once and you see the output immediately, so "reusability"
doesn't matter.

Aaron Meurer

>
> David
>
>
>
> --
> You received this message because you are subscribed to the Google Groups "sympy" group.
> To unsubscribe from this group and stop receiving emails from it, send an email to sympy+un...@googlegroups.com.
> To view this discussion on the web visit https://groups.google.com/d/msgid/sympy/ff6db073-aefc-6298-cfb3-aa0d14e8a63c%40dbailey.co.uk.
Reply all
Reply to author
Forward
0 new messages