I made a test of shadowing Python's built-in string module with my own
module named 'string', to test module search path behavior. My custom
string script has only print('string' * 2) for contents. It is
located in the current directory as shown in code below.
Python 3.6.4 |Anaconda custom (64-bit)| (default, Jan 16 2018, 10:22:32) [MSC v.1900 64 bit (AMD64)]
Type 'copyright', 'credits' or 'license' for more information
IPython 6.2.1 -- An enhanced Interactive Python. Type '?' for help.
In [1]: %pwd
Out[1]: 'C:\\Users\\stephen'
In [2]: import string
In [3]: string
Out[3]: <module 'string' from 'C:\\ProgramData\\Anaconda3\\lib\\string.py'>
In [4]: import imp
In [5]: imp.reload(string)
stringstring
Out[5]: <module 'string' from 'C:\\Users\\stephen\\string.py'>
Three questions about reload in IPython:
Why did reload think the module it actually imported (the local string.py) had already been imported? Is it just the sameness of file
name?
Why did reload import a different module than the one already imported? Did it skip the check of sys.modules dictionary, which was
checked first during original import?
Why did reload/IPython/Python not know it had pulled a fast one here, switching one module for another?
Edit: In going back and forth trying to take care of Stack Overflow complaining about my code block, I inadvertently lost some of what I meant to say. Here is what I can remember:
IPython is adding the built-in string module to sys.modules dictionary at startup (sys.modules is searched before sys.path), something the regular Python interactive prompt doesn't do. So I got a different behavior from the interactive prompt vs. IPython. With the interactive prompt, I always got the local string.py, since sys.path starts with current directory for module search. So, this much I understand about the difference between regular interactive (Anaconda) and IPython. The questions I listed are what remain confusing for me.
reload is supposed to repeat the process of locating the source code for the module it's reloading, and if it finds a different file from what the original import found, it's supposed to use the new file. After all, it needs to handle cases where a module was moved, or where a normal module was changed to a package or an extension module.
reload is not supposed to look at sys.modules and stop if it finds something. If it did that, it would perform no reloading!
The reason reload finds the local string.py file when the initial IPython-internal import didn't is because the import path has changed since the first import. You ran IPython in a way that doesn't cause Python itself to put the working directory on the module search path, and IPython imported the string module from the standard library under that configuration. Afterward, IPython placed the working directory on the module search path itself, mimicking regular interactive Python, so reload found the local string.py.
Tested on my Kernel
Looks you are using a local module name that shadows the name of a standard library or third party package or module that the application relies on. Python imports usually check from the the sys.path setting which might be set under Users\stephen. Hence when we reload it, it picks the first occurrence. Hope it helps.
For reference: https://python-notes.curiousefficiency.org/en/latest/python_concepts/import_traps.html
Related
I am using following python version in Debian Stable Linux:
Python 3.5.3 (default, Jan 19 2017, 14:11:04)
[GCC 6.3.0 20170118] on linux
I find following code does not work:
print(math.sqrt(10))
The error is:
print(math.sqrt(10))
NameError: name 'math' is not defined
This error disappears and code works fine if following is added:
import math
This seems inconsistent with documentation on https://docs.python.org/3.5/library/math.html where it says This module is always available. Where is the problem? Is there some problem in my python setup?
Nothing wrong with the setup. The phrase
This module is always available
simply means that in every environment you should be able to import the standard math module.
Since that phrase states that what you are seeing is a module and it also stated in Python's documentation that modules need to be imported I wouldn't call it inconsistent.
I have a big C++ module with Python 3 bindings using Boost.Python, that I compile to a .so file using CMake on macOS.
When I try to import it in the REPL, everything seems to work fine:
>>>import myModule
>>>
However, as soon as I run the import statement, the famous rocket icon of Python shows up in the Dock and stays there jumping for some minutes and stops after. Obviously then, I cannot access any of the functions defined in my module, so the import looks fine but doesn't actually do anything.
I tried looking in the Console and saw that whenever I import myModule, I get two launchservicesd[83]: SecTaskLoadEntitlements failed error=22.
It brought me to this and that related questions but I can't find what the exact problem is.
The C++ module is huge so I just can't look at the code and find the problem, thus I'm asking for any hints about at least how to debug that problem.
I can suggest the following steps:
Try to import that module though local python session. So, run interactive python interpreter, and 'import myModule'.
If bad, try to check:
are python version, with which myMoudle was linked with, is similiar to used interpreter
check that build architectires are the same
check that you can load even simple boost.python example module
If ok, check that you have correctly set up module search path in your python code.
I have seen many mentions of usercustomize throughout the docs. What is it exactly?
I am on Ubuntu 12.0, Python 3.3, using the IDLE interpreter.
Adding a 'usercustomize.py' file to /usr/lib/python3.3 with the following code in it:
import math
I started the IDLE interpreter. Without importing math, I typed math.sqrt(
Typing Ctrl + \ to start the auto complete suggestion, I get a prompt like sqrt(x). This suggests that math in fact has been imported. But actually calling the function raises NameError.
What exactly is going on here?
See the site module for full documenation on what usercustomize is meant to do.
Note that usercustomize is only imported if site.ENABLE_USER_SITE is enabled:
After this, an attempt is made to import a module named usercustomize, which can perform arbitrary user-specific customizations, if ENABLE_USER_SITE is true. This file is intended to be created in the user site-packages directory (see below), which is part of sys.path unless disabled by -s. An ImportError will be silently ignored.
Importing math into usercustomize will not make it available in IDLE; you are not making it a built-in that way. You could add it to the builtins module, but I'd advice against that.
usercustomize is not meant to set up a default IDLE environment, it is meant to add extra entries to the sys.path module search path and other general Python runtime environment changes.
The Python documentation says that sys.path is "Initialized from the environment variable PYTHONPATH, plus an installation-dependent default."
But what is the "installation-dependent default" exactly for Windows?
(I know this is probably dependent on how python was compiled, but if all I have is the binary, is there any way to figure out how the default sys.path is constructed?)
Clarification:
I am not asking "What is my sys.path?". I want to know "how does Python construct sys.path?" Documentation says that sys.path is constructed with sys.path[0] being the script's current directory, plus whatever Python finds in the PYTHONPATH environment variable, plus some installation-dependent voodoo. So what is this mysterious voodoo part?
Seems like Praveen Gollakota has good info at Troubleshooting python sys.path (repasted here:)
The first that is added C:\WINNT\system32\python27.zip (more details in PEP273).
Next ones that are added are from entries in windows registry. The entries C:\Python27\DLLs;C:\Python27\lib; C:\Python27\lib\plat-win; C:\Python27\lib\lib-tk come from HOT_KEY_LOCAL_USER/Python/PythonCore/2.7/PythonPath in the registry. More details in Python source code comments here http://svn.python.org/projects/python/trunk/PC/getpathp.c (These entries were the trickiest for me to understand until I found the link above).
Next, as explained in the site package documentation, sys.path is built from sys.prefix and sys.exec_prefix. On my computer both of them point to C:\Python27. And by default it searches the lib/site-packages anyway. So now the entries C:\Python27; C:\Python27\lib\site-packages are appended to the list above.
Next it searches each of the .pth files in alphabetical order. I have easy_install.pth, pywin32.pth and setuptools.pth in my site-packages. This is where things start getting weird. It would be straightforward if the entries in the .pth files were just directory locations. They would just get appended to the sys.path line by line. However easy_install.pth has some python code that causes the entries listed in easy_install.pth to add the packages list at the beginning of the sys.path list.
After this the directory entries in pywin32.pth, setuptools.pth are added at the end of the sys.path list as expected.
Note: While the above discussion pertains to Windows, it is similar even on Mac etc. On Mac it just adds different OS defaults like darwin etc. before it starts looking at site-packages directory for .pth files.
The best way is to examine the actual path in your python interpreter:
$ python
Python 2.6.6 (r266:84297, Aug 24 2010, 18:13:38) [MSC v.1500 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> import pprint, sys
>>> pprint.pprint(sys.path)
['',
'c:\\Python26\\lib\\site-packages\\setuptools-0.6c11-py2.6.egg',
'c:\\Python26\\lib\\site-packages\\nose-1.0.0-py2.6.egg',
'C:\\Windows\\system32\\python26.zip',
'c:\\Python26\\DLLs',
'c:\\Python26\\lib',
'c:\\Python26\\lib\\plat-win',
'c:\\Python26\\lib\\lib-tk',
'c:\\Python26',
'c:\\Python26\\lib\\site-packages',
'c:\\Python26\\lib\\site-packages\\win32',
'c:\\Python26\\lib\\site-packages\\win32\\lib',
'c:\\Python26\\lib\\site-packages\\Pythonwin',
'c:\\Python26\\lib\\site-packages\\wx-2.8-msw-unicode']
Have you tried importing sys and then printing sys.path? It would appear that it contains the following on my Windows 7 system:
'',
'C:\\Windows\\system32\\python26.zip',
'c:\\python26\\DLLs',
'c:\\python26\\lib',
'c:\\python26\\lib\\plat-win',
'c:\\python26\\lib\\lib-tk',
'c:\\python26',
'c:\\python26\\lib\\site-packages',
'c:\\python26\\lib\\site-packages\\win32',
'c:\\python26\\lib\\site-packages\\win32\\lib',
'c:\\python26\\lib\\site-packages\\Pythonwin',
'c:\\python26\\lib\\site-packages\\wx-2.8-msw-unicode'
This corresponds to the packages I've installed, as I haven't ever needed to set a custom PYTHONPATH variable.
I am teaching myself python from this site. On Chapter 3, when I typed the code in the given example, I got the following error--
Python 3.2 (r32:88445, Mar 25 2011, 19:28:28)
[GCC 4.5.2] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import turtle
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "turtle.py", line 2, in <module>
wn = turtle.Screen()
AttributeError: 'module' object has no attribute 'Screen'
>>>
Is this something that I need to download and install? I tried looking into docs.python.org, but my nose started to bleed reading all that tech stuff.
Kindly point me in the right direction please? Thank you.
Adam Bernier's answer is probably correct. It looks like you have a file called turtle.py that Python is picking up before the one that came with your Python installation.
To track down these problems:
% python
Python 2.7.1 (r271:86832, Jan 29 2011, 13:30:16)
[GCC 4.2.1 (Apple Inc. build 5664)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import sys
>>> sys.path
[...] # Your ${PYTHONPATH}
>>> import turtle
>>> turtle.__file__
'/opt/local/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/lib-tk/turtle.pyc' # Should be under your Python installation.
>>>
If you see something like this:
>>> import turtle
>>> turtle.__file__
'turtle.py'
Then you'll want to move turtle.py (and any corresponding turtle.pyc or turtle.pyo files) in your current working directory out of the way.
As per the comments below, you'll find a wealth of information about a module, including its pathname and contents by calling help() upon it. For example:
>>> import turtle
>>> help(turtle)
Rename turtle.py. It is clashing with the imported module of the same name.
I tested that the code from that site works in Python 2.6 (without installing any external packages).
From http://docs.python.org/tutorial/modules.html#the-module-search-path
When a module named spam is imported, the interpreter searches for a file named spam.py in the current directory, and then in the list of directories specified by the environment variable PYTHONPATH.
So the Python interpreter is finding your turtle.py file, but not seeing a Screen class within that file.
Johnsyweb's answer contains several good tips on how to debug this kind of issue. Perhaps the most direct way of determining where on the filesystem an imported module resides is to use repr(module) or simply type the module name at the REPL prompt, e.g.:
>>> turtle
<module 'turtle' from '/usr/lib/python2.6/lib-tk/turtle.pyc'>
Another problem that people may encounter is due to an installation issue on Linux systems. On my Windows machine, 'turtle' was just there and I was able to import turtle with no problem. When I tried to import turtle in Ubuntu, it didn't find the module, so I tried to install it.
When I did sudo pip install turtle, it installed a package 'turtle' which apparently is very different: "Turtle is an HTTP proxy whose purpose is to throttle connections to specific hostnames ...." This 'turtle' most certainly does not have "Screen" or anything related to a little drawing turtle. So I ended up with the same error as the user in the question of module has no attribute 'Screen'.
For Ubuntu, what I needed to do was:
sudo pip uninstall turtle
sudo apt-get install python-tk
Then when I did import turtle, all of the expected modules were found.
Go to the directory where you save your python files. There is a file named turtle.py. Either remove it, or rename it. This will work.
thanks,
Probably not related, but I spent some time tracking down this same error and found a different cause: I had a file named "copy.py" in the folder with my project.
This "copy.py" was an assignment to make a function that returns a deep copy of a list. The turtle library imports "deepcopy" from "copy"; turns out there's already a "copy.py" as part of python (which I'd never seen/used) & by having a file named "copy.py" in my project folder, it was causing turtle to import the wrong copy.py, which was causing the error to be thrown in turtle (my copy.py assignment's deepcopy function didn't work the same way as the one in python).
This is a more general suggestion, but it's good to double check and make sure you don't have any filenames that are in conflict with actual python imports used in your project. There are too many to list here, but ones used by turtle include: tkinter, types, math, time, inspect, sys, and copy. If you have any of these with a .py in your folder (for example, if you had previously created an inspect.py), turtle will be loading that instead of the built-in library & will not work.