There seem to be file names that are not allowed to exist in the same directory in which I'm running my Python source code because they probably conflict with a file of the same name within a module in which I've imported.
Is there a way to still keep the names the same but avoid the exception?
This seems bizarre being how long Python has been around and is not fixed or the default install of Python doesn't avoid this, despite what modules are imported (ie: openpyxl in the copy.py scenario & smtplib in the email.py scenario).
Below are two example exceptions. My source code is in the testing.py file. And files copy.py and email.py are in the same directory as testing.py. For now, I renamed them to copy2.py and email2.py, but this seems like a bad workaround.
copy.py
Traceback (most recent call last):
File "C:\Python\Python37_64\lib\runpy.py", line 193, in _run_module_as_main
"__main__", mod_spec)
File "C:\Python\Python37_64\lib\runpy.py", line 85, in _run_code
exec(code, run_globals)
File "C:\Python\Python37_64\lib\cProfile.py", line 185, in <module>
main()
File "C:\Python\Python37_64\lib\cProfile.py", line 178, in main
runctx(code, globs, None, options.outfile, options.sort)
File "C:\Python\Python37_64\lib\cProfile.py", line 20, in runctx
filename, sort)
File "C:\Python\Python37_64\lib\profile.py", line 62, in runctx
prof.runctx(statement, globals, locals)
File "C:\Python\Python37_64\lib\cProfile.py", line 100, in runctx
exec(cmd, globals, locals)
File "C:\GitLab\redcap-p01-etl\testing.py", line 7, in <module>
import openpyxl # openpyxl 3.0.7
File "C:\Python\venv\Python37_64\lib\site-packages\openpyxl\__init__.py", line 6, in <module>
from openpyxl.workbook import Workbook
File "C:\Python\venv\Python37_64\lib\site-packages\openpyxl\workbook\__init__.py", line 4, in <module>
from .workbook import Workbook
File "C:\Python\venv\Python37_64\lib\site-packages\openpyxl\workbook\workbook.py", line 4, in <module>
from copy import copy
File "C:\GitLab\p01\copy.py", line 2
def parse_slash_copy(const char *args):
^
IndentationError: unexpected indent
email.py
Traceback (most recent call last):
File "C:\Python\Python37_64\lib\runpy.py", line 193, in _run_module_as_main
"__main__", mod_spec)
File "C:\Python\Python37_64\lib\runpy.py", line 85, in _run_code
exec(code, run_globals)
File "C:\Python\Python37_64\lib\cProfile.py", line 185, in <module>
main()
File "C:\Python\Python37_64\lib\cProfile.py", line 178, in main
runctx(code, globs, None, options.outfile, options.sort)
File "C:\Python\Python37_64\lib\cProfile.py", line 20, in runctx
filename, sort)
File "C:\Python\Python37_64\lib\profile.py", line 62, in runctx
prof.runctx(statement, globals, locals)
File "C:\Python\Python37_64\lib\cProfile.py", line 100, in runctx
exec(cmd, globals, locals)
File "C:\GitLab\p01\testing.py", line 13, in <module>
import requests
File "C:\Python\venv\Python37_64\lib\site-packages\requests\__init__.py", line 43, in <module>
import urllib3
File "C:\Python\venv\Python37_64\lib\site-packages\urllib3\__init__.py", line 11, in <module>
from . import exceptions
File "C:\Python\venv\Python37_64\lib\site-packages\urllib3\exceptions.py", line 3, in <module>
from .packages.six.moves.http_client import IncompleteRead as httplib_IncompleteRead
File "C:\Python\venv\Python37_64\lib\site-packages\urllib3\packages\six.py", line 199, in load_module
mod = mod._resolve()
File "C:\Python\venv\Python37_64\lib\site-packages\urllib3\packages\six.py", line 113, in _resolve
return _import_module(self.mod)
File "C:\Python\venv\Python37_64\lib\site-packages\urllib3\packages\six.py", line 82, in _import_module
__import__(name)
File "C:\Python\Python37_64\lib\http\client.py", line 71, in <module>
import email.parser
File "C:\GitLab\p01\email.py", line 1, in <module>
import smtplib
File "C:\Python\Python37_64\lib\smtplib.py", line 47, in <module>
import email.utils
ModuleNotFoundError: No module named 'email.utils'; 'email' is not a package
CodePudding user response:
This seems bizarre being how long Python has been around and is not fixed or the default install of Python doesn't avoid this, despite what modules are imported
It is not fixed or avoided because it is considered to be working as intended. In the default configuration, any time Python loads modules, it looks for the module in various paths, defined in a list that is accessible as sys.path
.
From the documentation:
As initialized upon program startup, the first item of this list,
path[0]
, is the directory containing the script that was used to invoke the Python interpreter. If the script directory is not available (e.g. if the interpreter is invoked interactively or if the script is read from standard input),path[0]
is the empty string, which directs Python to search modules in the current directory first. Notice that the script directory is inserted before the entries inserted as a result ofPYTHONPATH
.
In your case, then, path[0]
is C:\GitLab\p01
, which is definitely not a place to look for standard library modules.
Personally, I am not very happy with the design decision (I would prefer, in particular, that new programmers are forced to get their heads around relative imports ASAP), but it is a conscious design decision, and one that enables quite a bit of convenience.
Is there a way to still keep the names the same but avoid the exception?
If you insist - you can simply hack sys.path
:
import sys
local = sys.path.pop(0)
import requests
sys.path.insert(0, local)
This will not necessarily be compatible with any other hacks you might attempt to sys.path
anywhere else in the program (but at least you can ensure that the change is immediately reverted after the otherwise-problematic imports). You will be stuck with something like this for every import (optimistically, sequence of imports) that conflicts with the name you want. And, of course, if you want to use the name sys
you are out of luck.
You can wrap this up in a variety of ways; and you can hook into the import system in a variety of ways. It is possible (but potentially very dangerous) to do dynamic imports (i.e., from a string that contains a URI), and it is possible to alter the mechanisms that import
uses. This is a broad research topic, beyond the scope of a Stack Overflow answer.
CodePudding user response:
Python ships with a number of modules, such as json
, collections
, copy
and email
. A complete list can be found in the official documentation.
Since module/package names are globally unique per interpreter sessions, using custom modules/packages with the same name as a built in module makes the latter inaccessible by their given name. This means that any code trying to access the builtin modules – be it your own or third-party code – will likely fail.
There is no workaround for this. Do not re-use names of builtin modules/packages unless you purposely want to replace them. This includes removing leftover code with such naming conflicts. Either rename the conflicting files, or move them out of the searched paths.