Django4.2执行自定义命令报AttributeError: 'PosixPath'无startswith属性
Django 4.2 + Python 3.10执行自定义manage.py命令触发AttributeError的解决与相关问题
问题场景
- 开发环境:Python 3.10.10、Django 4.2
- 执行自定义命令:
python manage.py run_cmdb_worker - 报错核心信息:
AttributeError: 'PosixPath' object has no attribute 'startswith'
完整报错回溯:
# python manage.py run_cmdb_worker Traceback (most recent call last): File "/usr/local/python/lib/python3.10/pkgutil.py", line 417, in get_importer importer = sys.path_importer_cache[path_item] KeyError: PosixPath('/www/cloudadmin') During handling of the above exception, another exception occurred: Traceback (most recent call last): File "/www/cloudadmin/manage.py", line 22, in <module> main() File "/www/cloudadmin/manage.py", line 18, in main execute_from_command_line(sys.argv) File "/opt/.pyvenv/lib/python3.10/site-packages/django/core/management/__init__.py", line 442, in execute_from_command_line utility.execute() File "/opt/.pyvenv/lib/python3.10/site-packages/django/core/management/__init__.py", line 436, in execute self.fetch_command(subcommand).run_from_argv(self.argv) File "/opt/.pyvenv/lib/python3.10/site-packages/django/core/management/__init__.py", line 275, in fetch_command klass = load_command_class(app_name, subcommand) File "/opt/.pyvenv/lib/python3.10/site-packages/django/core/management/__init__.py", line 48, in load_command_class module = import_module("%s.management.commands.%s" % (app_name, name)) File "/usr/local/python/lib/python3.10/importlib/__init__.py", line 126, in import_module return _bootstrap._gcd_import(name[level:], package, level) File "<frozen importlib._bootstrap>", line 1050, in _gcd_import File "<frozen importlib._bootstrap>", line 1027, in _find_and_load File "<frozen importlib._bootstrap>", line 1006, in _find_and_load_unlocked File "<frozen importlib._bootstrap>", line 688, in _load_unlocked File "<frozen importlib._bootstrap_external>", line 883, in exec_module File "<frozen importlib._bootstrap>", line 241, in _call_with_frames_removed File "/www/cloudadmin/apps/cmdb/management/commands/run_cmdb_worker.py", line 2, in <module> from cmdb.scheduler import Scheduler File "/www/cloudadmin/apps/cmdb/scheduler.py", line 3, in <module> from apscheduler.schedulers.background import BackgroundScheduler File "/opt/.pyvenv/lib/python3.10/site-packages/apscheduler/__init__.py", line 1, in <module> from pkg_resources import get_distribution, DistributionNotFound File "/opt/.pyvenv/lib/python3.10/site-packages/pkg_resources/__init__.py", line 3260, in <module> def _initialize_master_working_set(): File "/opt/.pyvenv/lib/python3.10/site-packages/pkg_resources/__init__.py", line 3234, in _call_aside f(*args, **kwargs) File "/opt/.pyvenv/lib/python3.10/site-packages/pkg_resources/__init__.py", line 3272, in _initialize_master_working_set working_set = WorkingSet._build_master() File "/opt/.pyvenv/lib/python3.10/site-packages/pkg_resources/__init__.py", line 572, in _build_master ws = cls() File "/opt/.pyvenv/lib/python3.10/site-packages/pkg_resources/__init__.py", line 565, in __init__ self.add_entry(entry) File "/opt/.pyvenv/lib/python3.10/site-packages/pkg_resources/__init__.py", line 621, in add_entry for dist in find_distributions(entry, True): File "/opt/.pyvenv/lib/python3.10/site-packages/pkg_resources/__init__.py", line 1988, in find_distributions importer = get_importer(path_item) File "/usr/local/python/lib/python3.10/pkgutil.py", line 421, in get_importer importer = path_hook(path_item) File "<frozen importlib._bootstrap_external>", line 1632, in path_hook_for_FileFinder File "<frozen importlib._bootstrap_external>", line 1504, in __init__ File "<frozen importlib._bootstrap_external>", line 182, in _path_isabs AttributeError: 'PosixPath' object has no attribute 'startswith'
已验证的解决方法
修改项目settings.py中的BASE_DIR配置,将默认的Path对象替换为字符串路径:
# 原默认配置(触发报错) # BASE_DIR = Path(__file__).resolve().parent.parent # 修改后的配置(解决问题) BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
相关问题情况
这个问题并非个例,不少开发者都遇到过。根源在于旧版本的setuptools(其依赖的pkg_resources模块)不兼容Django 4.2默认使用的PosixPath/WindowsPath对象。当项目中某个依赖(比如本次场景中的APScheduler)导入pkg_resources时,该模块在处理sys.path中的Path对象时会触发类型错误。
除了替换BASE_DIR为字符串的方法,另一种更推荐的解决方案是升级setuptools到60.0.0及以上版本——新版本的pkg_resources已经修复了对Path对象的兼容问题,升级后可以保留Django默认的Path类型BASE_DIR配置,执行以下命令即可升级:
pip install --upgrade setuptools
内容的提问来源于stack exchange,提问作者David Du
相关产品推荐
相关产品推荐

