# Check for name clashes in startproject without importing modules

**URL:** <https://forum.djangoproject.com/t/check-for-name-clashes-in-startproject-without-importing-modules/23091>\
**Category:** Django Internals\
**Created:** [August 16, 2023, 3:12am UTC](https://forum.djangoproject.com/t/check-for-name-clashes-in-startproject-without-importing-modules/23091 "2023-08-16T03:12:21Z")\
**Posts on this page:** 4\
**Page:** 1

<div class="post-metadata">

**Author:** ![jacobtylerwalls](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.djangoproject.com/jacobtylerwalls/32/30603_2.png) [@jacobtylerwalls](https://forum.djangoproject.com/u/jacobtylerwalls)\
**Post date:** [August 16, 2023, 3:12am UTC](https://forum.djangoproject.com/t/check-for-name-clashes-in-startproject-without-importing-modules/23091/1 "2023-08-16T03:12:21Z")

</div>

Hey all,

I’d like to propose a small cleanup ([ticket-34778](https://code.djangoproject.com/ticket/34778)): when the `startproject` command checks for name clashes with other modules, it could just use importlib’s `find_spec()` ([docs](https://docs.python.org/3/library/importlib.html?highlight=find_spec#importlib.util.find_spec)), which checks for the presence of a module without importing it. Right now the command tries to import modules and depends on an exception being raised in the absence of one.

_Why?_  
Importing modules can execute code, e.g. dumping to the terminal or importing other further modules. (Of course, the user has trusted any hypothetical same-named modules by having installed them already, but it just seems polite to stop at checking for existence when that’s all we need for the name clash check.)

_Who might this help?_  
My team is wrapping the `startproject` command to help people create instances of our software, let’s call it `presto`. A user might do something like use our command to create a project called `presto-education`. But what if they’ve installed someone else’s module called `presto-education` before there was a cool `startpresto`-way to get everything they need to use `presto` for education? The kinds of users we’re making this command for are not full-time Django developers. We write explicit instructions helping them accomplish their upgrades. I noticed this in code review and saw that we were just extending Django’s behavior. (I opened a ticket and Natalia helpfully suggested raising a forum post.)

The diff would look like:

```auto
diff --git a/django/core/management/templates.py b/django/core/management/templates.py
index 8c2232ee7a..ec4a4b4214 100644
--- a/django/core/management/templates.py
+++ b/django/core/management/templates.py
@@ -5,7 +5,7 @@ import posixpath
 import shutil
 import stat
 import tempfile
-from importlib import import_module
+from importlib.util import find_spec
 from urllib.request import build_opener
 
 import django
@@ -277,11 +277,7 @@ class TemplateCommand(BaseCommand):
                 )
             )
         # Check it cannot be imported.
- try:
- import_module(name)
- except ImportError:
- pass
- else:
+ if "." in name or find_spec(name) is not None:
             raise CommandError(
                 "'{name}' conflicts with the name of an existing Python "
                 "module and cannot be used as {an} {app} {type}. Please try "

```

Of course, this is a judgment call. Maybe not worth bothering. We haven’t even shipped our wrapped command yet. But this came up in code review and I wanted to “offer it back upstream”.

Your thoughts welcome!

---

<div class="post-metadata">

**Author:** ![carltongibson](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.djangoproject.com/carltongibson/32/267_2.png) [@carltongibson](https://forum.djangoproject.com/u/carltongibson)\
**Post date:** [August 16, 2023, 7:58am UTC](https://forum.djangoproject.com/t/check-for-name-clashes-in-startproject-without-importing-modules/23091/2 "2023-08-16T07:58:17Z")

</div>

Hi @jacobtylerwalls, this seems reasonable as described. (Are there any gotchas? If not 👍) Thanks!

---

<div class="post-metadata">

**Author:** ![adamchainz](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.djangoproject.com/adamchainz/32/26_2.png) [@adamchainz](https://forum.djangoproject.com/u/adamchainz)\
**Post date:** [August 16, 2023, 9:04am UTC](https://forum.djangoproject.com/t/check-for-name-clashes-in-startproject-without-importing-modules/23091/3 "2023-08-16T09:04:48Z")

</div>

Seems fair to me too.

---

<div class="post-metadata">

**Author:** ![jacobtylerwalls](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.djangoproject.com/jacobtylerwalls/32/30603_2.png) [@jacobtylerwalls](https://forum.djangoproject.com/u/jacobtylerwalls)\
**Post date:** [August 16, 2023, 11:04am UTC](https://forum.djangoproject.com/t/check-for-name-clashes-in-startproject-without-importing-modules/23091/4 "2023-08-16T11:04:31Z")

</div>

Thanks for the quick replies!

Couldn’t come up with a gotcha. If anything, this might find more name clashes, as some existing module might raise `ImportError` itself and pass the existing check.

(The check for dotted paths in my diff was because the benefit of `find_spec()` is partially lost in that case, since it _will_ import the parent, but the command already checks for dotted paths in the earlier part of this method, so this diff wouldn’t even need to check again.)
