今天在公众号粉丝群里,有同学提到了Python找不到模块的问题:问题中涉及的代码结构和代码截图如下:这个问题的解决方法很简单,把start.py文件移出bin文件夹即可。但是如果我们进一步分析这个问题,我们可以看到更多的问题。在我之前的文章中:为什么Python代码运行起来PyCharm却给我画了一条红线?,我讲了工作区(Workdir)对代码的影响。PyCharm和VSCode识别的工作空间可能与您在终端窗口中直接运行.py文件时的工作空间不相同。今天这个问题本质上是工作空间引起的问题。这位同学的项目根目录是MY_API,所以他使用的编辑器VSCode会默认以MY_API为工作空间。因此,当他在start.py文件中写fromlib.interfaceimportserver时,VScode不会用红色波浪线标记他。因为从VSCode的角度来看,lib文件夹确实在workspace下。然而,当他在VSCode中运行start.py文件时,Python从bin文件夹中运行。此时,Python将使用bin文件夹作为工作区。workspace中只有这个start.py文件,当然找不到lib文件夹了。如果仅从技术上讲,您在bin文件夹的父文件夹下导入其他模块并不困难。我每天做一个技能:导入父文件夹下的模块,读取当前文件夹下的模块,具体方法参考资源文章。但问题是,你不应该这样做。项目的入口文件不要放在项目内部的深文件夹中。所谓入口文件就是先经过它再到达其他文件。当你拿到一个Python项目时,只需要从入口文件开始读取代码,根据入口文件调用的模块读取所有的实现逻辑。但是如果你经常访问Github,你会发现有些人可能被其他垃圾语言污染了。他的Python项目有五??六个文件夹,根目录下有七八个.py文件。当你拿到这个项目的时候,你甚至不知道要运行这段代码时应该运行哪个文件python3xxx.py。你查询了很多方法,或者看了半天文档才知道,哦,原来的入口文件是com/xx/yy/zz/script/run.py。当你打开这个run.py文件,你会发现在它的最上面,写着文件导入代码from../../../../aaaimportbbb。这只是疯狂的写作。我知道有些垃圾语言流行这样写。但是现在你正在使用Python,聪明点,不要那样写。对于Python项目,入口文件应该始终位于最外层。例如:当你想启动这个项目时,直接在最外层的python3main.py中启动即可。在main.py中,可以导入其他模块,然后调用其他模块中的类或函数。这样做有什么好处?通过这样做,您可以在项目的根目录下启动项目,因此您的工作区就是项目的根目录。然后,您可以根据任何.py文件中的工作区轻松导入任何其他文件。比如你现在在models/mongo-util/mongob_helper.py文件中,你想在utils/abc.py中导入time_format()函数,那么你只需要这样写。fromutils.abcimporttime_format你不可能导入父文件夹中的模块。只有工具脚本需要单独存放在一个文件夹中,然后调用父文件夹中的其他文件。比如我现在有一个工具脚本,每天晚上0点读写MongoDB,清理无效数据。这时候我可以在根目录下单独创建一个script或者tools或者bin文件夹,然后把tool脚本放在里面。例如:在这个工具脚本中,您可以调用models/mongo-util/mongob_helper.py文件中的一个函数。在这种情况下,您可以调用父文件夹的内容。但这毕竟只是一个工具脚本。有的同学可能会问,如果我的工程是一个没有入口文件的Python包怎么办?这时候你可以使用这个包的__init__.py作为它的入口文件。可以参考我在GitHub中的代码组织结构-kingname/GeneralNewsExtractor:NewsWebTextGeneralExtractorBetaVersion。在项目根目录留下一个example.py文件来演示如何调用这个包。包本身的代码在一个名为gne的文件夹中。这个gne文件夹是一个包,它的入口文件在__init__.py中。大家,写代码的时候,先想一想。如果别人拿到你的代码,想梳理一下这个项目的逻辑,你怎么不问你,让他知道从哪个文件读取??应该按什么顺序阅读?他能轻易看出数据在你的代码中是如何工作的吗?
