0

In a simple Program in BugTest.py:

from BugTest import *

print("Hello World")

note my error in importing BugTest.py from BugTest.py

Here is the output:

Hello World
Hello World

My question is: Why doesn't this cause a compile error? Is this a bug in Python?

Why does it only import twice, rather than enter an infinite loop?

Jacob Waters
  • 307
  • 1
  • 3
  • 11
  • *"note my error"* -- Sorry, what error? Do you mean the output wasn't what you were expecting? – wjandrea Nov 18 '22 at 23:14
  • Once you import something, next time you import it, it doesn't run the file again, it just references the module of same name that was previously imported, instead of running it again – Matiiss Nov 18 '22 at 23:14
  • 1
    @Matiiss Erm, Python does have a compiler, but it's not often used directly. Python source code is compiled to byte code, then the byte code is run on the Python virtual machine. A `SyntaxError` can be considered a compile error. – wjandrea Nov 18 '22 at 23:16
  • @wjandrea right, well, good to know now, had to research this a bit, thought everything was done by the interpreter... – Matiiss Nov 18 '22 at 23:19
  • I could have sworn there is a canonical duplicate for this, but I have no idea how to search for it at the moment. – Karl Knechtel Nov 18 '22 at 23:25
  • @Karl Maybe [python import multiple times](/q/37067414/4518341)? – wjandrea Nov 18 '22 at 23:33
  • 1
    @wjandrea I feel that a module importing itself is objectively an error(at least in terms of readability). I hate absolutes but I cant think of a time where you would want all the code in your module to run twice, and would opt to do it this way as opposed to a loop. – Jacob Waters Nov 18 '22 at 23:33
  • 1
    @wjandrea that looks more like a duplicate of the canonical that I referenced in my answer. Simply knowing that there is a module cache only gets you part of the way there. A canonical for this question would need to talk about the special `__main__` name for modules too. – Karl Knechtel Nov 18 '22 at 23:35
  • I guess I feel that it's an obviously-bad enough thing to do I'm surprised Python didn't catch it with an error – Jacob Waters Nov 18 '22 at 23:35
  • 3
    Python is **generally** not in the habit of nannying the programmer on "obviously-bad" things. "That's not the right way to do it" is the responsibility of the community (and documents like PEP 8 and PEP 20), not `python.exe`. – Karl Knechtel Nov 18 '22 at 23:37
  • 2
    @Matiiss probably the only *purely* interpreted language people really use today are shell languages like `bash` etc – juanpa.arrivillaga Nov 18 '22 at 23:38
  • @JacobWaters the code won't run twice, unless it is the entrypoint (and this is, IMO a wart, because essentially, the entry point goes into the module cache as `"__main__"` so it would get re-imported – juanpa.arrivillaga Nov 18 '22 at 23:39
  • @Jacob Ah yeah, it certainly feels like bad style. But it's not an error, cause "error" means the program tried to do something that's explicitly not allowed. – wjandrea Nov 18 '22 at 23:40

2 Answers2

4

Why doesn't this cause a compile error?

Because it's completely valid syntax. The only error (absent a problem in the Python runtime itself, such as running out of memory or failing to find the source code) that can occur at compile time in Python is SyntaxError. Names are only resolved at runtime.

That said, it's also completely valid at runtime.

Why does it only import twice, rather than enter an infinite loop?

from BugTest import * means - roughly - "look for an existing module named BugTest; if not found, find and load BugTest.py, create a module object from it named BugTest, and put it in the module cache. Then, copy all the names from the BugTest module into the current module (overwriting any existing names)."

When you run the program, Python creates a module object from the BugTest.py code, and (very usefully) gives it the special name __main__. Then it runs the top-level code, triggering the import statement. Now it creates another module object from the BugTest.py code, giving it the usual name of BugTest. That module's top-level code runs as well; but when it tries to import, a BugTest module is already in the module cache.

Karl Knechtel
  • 62,466
  • 11
  • 102
  • 153
2

You executed

$ python BugTest.py

which asked for two statements to run, an import and a print.

The pair of statements ran exactly once.

The first statement performed an import, which has the side effect of printing a line.

Then the second statement, a print, printed a line as requested.

Everything happened according to plan.


It is usually considered undesirable for an import to have side effects such as print(). In this case, of course, it makes perfectly good sense during debugging.


Once imported, a module appears in a hash table and will not be re-imported again. So attempting a double import here would not provoke three lines of output.

That is, having done (a possibly time consuming) import x, we won't see x imported again. If top-level, or any transitive dependencies imported by top-level, asks for import x, it is simply skipped, as a cache hit.

J_H
  • 17,926
  • 4
  • 24
  • 44