3

I have a Python script which imports the datetime module. It works well until someday I can run it in a directory which has a Python script named datetime.py. Of course, there are a few ways to resolve the issue. First, I run the script in a directory that does not contain the script datetime.py. Second, I can rename the Python script datetime.py. However, neither of the 2 approaches are perfect ways. Suppose one ship a Python script, he never knows where users will run the Python script. Another possible fix is to prevent Python from search the current working directory for modules. I tried to remove the empty path ('') from sys.path but it works in an interactive Python shell but not in a Python script. The invoked Python script still searches the current path for modules. I wonder whether there is any way to disable Python from searching the current path for modules?

if __name__ == '__main__':
    if '' in sys.path:
        sys.path.remove('')
    ...

Notice that it deosn't work even if I put the following code to the beginning of the script.

import sys
if '' in sys.path:
    sys.path.remove('')

Below are some related questions on StackOverflow.

Removing path from Python search module path

pandas ImportError C extension when io.py in same directory

initialization of multiarray raised unreported exception python

Benjamin Du
  • 1,391
  • 1
  • 17
  • 25
  • I think you should just rename it. `datetime` is a part of python's standard library. There are reserved words that you shouldn't use for programming, just the same as there are names you shouldn't name your python modules. – Andrew Grass Aug 12 '19 at 22:54
  • Just rename your script to something else (that doesn't exist in *Python* standard library). Anything else (even if it works), would simply be a lame workaround (*gainarie*). – CristiFati Aug 12 '19 at 22:58
  • 2
    `datetime` is just one obvious example. How about `abc.py` and how about other built-in modules that I even never heard of? If you ship a Python script, you cannot expect users to always run it in a perfect environment, right? – Benjamin Du Aug 12 '19 at 22:59
  • 1
    I think if your users are technical enough to have this problem, they're technical enough to solve it. Most python tools are installed with `pip`, which would guard against this. – Ben Aug 12 '19 at 23:00
  • A Python package might also suffer from this issue if it also installs Python scripts. – Benjamin Du Aug 12 '19 at 23:03
  • How do you figure? – juanpa.arrivillaga Aug 12 '19 at 23:06
  • What if your hypothetical users want to use both yours and python's ```datetime.py```? Causing unusual behaviour just because you don't want to name your files appropriately can make it harder for them to do so. – Andrew Grass Aug 12 '19 at 23:15
  • And you think that trying to manipulate `sys.path` or otherwise change Python's default behavior is somehow going to be a *better* experience for users of your code? Just rename your modules, and structure your project so that all your modules are in a single namespace. – larsks Aug 13 '19 at 02:27

1 Answers1

4

Are you sure that Python is searching for that module in the current directory, and not on the script directory? I don't think Python adds the current directory to the sys.path, except in one case. Doing so could even be a security risk (akin to having . on the UNIX PATH).

According to 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

So, '' as a representation of the current directory happens only if run from interpreter (that's why your interactive shell test worked) or if the script is read from the standard input (something like cat modquest/qwerty.py | python). Neither is a rather 'normal' way of running Python scripts, generally.

I'm guessing that your datetime.py stands side by side with your actual script (on the script directory), and that it just happens that you're running the script from that directory (that is script directory == current directory).

If that's the actual scenario, and your script is standalone (meaning just one file, no local imports), you could do this:

sys.path.remove(os.path.abspath(os.path.dirname(sys.argv[0])))

But keep in mind that this will bite you in the future, once the script gets bigger and you split it into multiple files, only to spend several hours trying to figure out why it is not importing the local files...

Another option is to use -I, but that may be overkill:

-I

Run Python in isolated mode. This also implies -E and -s. In isolated mode sys.path contains neither the script’s directory nor the user’s site-packages directory. All PYTHON* environment variables are ignored, too. Further restrictions may be imposed to prevent the user from injecting malicious code.

caxcaxcoatl
  • 8,472
  • 1
  • 13
  • 21