我遇到了一个Python'ImportError:No module named ...'错误,尝试从另一个Python包中的模块导入另一个Python包中的Python模块。 下图显示了目录结构:
必须注意的是,只有当我从终端运行脚本时才会出现此错误,而在通过PyCharm执行时,此脚本成功运行。 从终端执行时的错误如下:
Traceback (most recent call last): File "social_networks/linked_data.py", line 15, in <module> from text_analysis.text_refinement import camel_case_split ImportError: No module named 'text_analysis'我尝试了不同的导入方式,如下所示,但没有成功:
方法1:
sys.path.insert(0, os.path.realpath('../text_analysis')) from text_analysis.text_refinement import camel_case_split方法2:
from text_analysis.text_refinement import camel_case_split这个问题的解决方案是什么?
I came across a Python 'ImportError: No module named...' error attempting to import a Python module which resides in another Python package from a module which resides within another Python package. The following image shows the directory structure:
It has to be noted that I get this error only when I run the script from my terminal whereas when executing through PyCharm, this script successfully runs. The error when executing from terminal is as follows:
Traceback (most recent call last): File "social_networks/linked_data.py", line 15, in <module> from text_analysis.text_refinement import camel_case_split ImportError: No module named 'text_analysis'I have tried different ways of importing such as the following without any success:
Method-1:
sys.path.insert(0, os.path.realpath('../text_analysis')) from text_analysis.text_refinement import camel_case_splitMethod-2:
from text_analysis.text_refinement import camel_case_splitWhat is the solution for this issue?
最满意答案
简洁版本
将其更改为:
sys.path.insert(0, os.path.realpath('./')) from text_analysis.text_refinement import camel_case_split要么:
sys.path.insert(0, os.path.realpath('./text_analysis')) from text_refinement import camel_case_split长版
我已在我的机器上重新创建了您的项目结构,并设法使其工作。 让我们一步一步走,这样我们就可以弄清楚发生了什么。
首先,我看到你正在PyCharm中开展你的项目。 它会自动将项目根添加到PYTHONPATH 。 您可以在此主题中详细了解此内容。 由于PyCharm会为您处理路径业务,因此您并不需要
sys.path.insert(0, os.path.realpath('../text_analysis'))让你的代码运行。 路径仍将添加,但不会用于定位包。 在你的机器上试试吧。 我想你会发现它是真的。 您可以通过运行轻松检查路径
for path in sys.path: print(path)虽然这是有趣的信息,但它没有回答您如何从终端运行它的问题。 要理解它不是从脚本运行的原因,让我们看看在方法1中执行(略微修改过的)命令时您将拥有哪些Python路径:
sys.path.insert(0, os.path.realpath('../text_analysis')) try: from text_analysis.text_refinement import camel_case_split camel_case_split() except: for path in sys.path: print(path) # output: # ~/text_analysis (where ../text_analysis path points to) # ~/social-network-interest-engine/social_networks (where your file is) # ... (several other irrelevant paths) ...我们可以看到'../text_analysis'一个目录指向您需要的目录之上 。 如果我们删除其中一个'./text_analysis' ,然后编写'./text_analysis'会发生什么? 输出似乎是我们需要的:
# output: # ~/social-network-interest-engine/text_analysis # ~/social-network-interest-engine/social_networks但是我们还没有导入这个功能。 我们知道这是因为我们到达了打印路径的except部分。 看看导入,我们可以看到我们有text_analysis.text_refinement 。 如果已经将目录名添加到路径中,我们是否真的需要说明目录名? 不我们没有。 如果我们写
from text_refinement import camel_case_split相反,我们发现该函数最终被导入。 遵循这个逻辑,假设我们想在import语句中留下text_analysis.text_refinement (无论出于何种原因),我们也可以不同地添加路径:
sys.path.insert(0, os.path.realpath('./'))但请注意,这种插入路径的方式有些脆弱。 起始位置是调用python python_file.py的路径。如果导航到不同的目录,则需要相应地调整os.path.realpath 。 你可以做什么:
sys.path.insert(0, 'full/path/to/application/app/folder')虽然这假设项目的目录/结构不会改变。
有关路径和导入的更深入概述,您可以在此处阅读有关从不同文件夹导入内容的更多信息,如果您更喜欢相对路径导入,则这是一个有用的线程。 当然, 官方文档也是一个很好的起点。
Short version
Change it to:
sys.path.insert(0, os.path.realpath('./')) from text_analysis.text_refinement import camel_case_splitOr:
sys.path.insert(0, os.path.realpath('./text_analysis')) from text_refinement import camel_case_splitLong version
I have recreated your project structure on my machine and managed to make it work. Let's go step by step, so that we can figure out what's happening.
First of all, I see you're working on your project in PyCharm. It automatically adds a project root to PYTHONPATH. You can read about this in detail in this thread. Since PyCharm takes care of path business for you, you do not really need
sys.path.insert(0, os.path.realpath('../text_analysis'))for your code to run. The path will still be added, but it will not be used to locate the package. Try it on your machine. I think you will find it to be true. You can easily check out paths by running
for path in sys.path: print(path)While this is interesting information, it does not answer your question how to run it from a terminal. To understand why it is not run from the script, lets see what Python paths you would have upon executing the (slightly modified) commands in method-1:
sys.path.insert(0, os.path.realpath('../text_analysis')) try: from text_analysis.text_refinement import camel_case_split camel_case_split() except: for path in sys.path: print(path) # output: # ~/text_analysis (where ../text_analysis path points to) # ~/social-network-interest-engine/social_networks (where your file is) # ... (several other irrelevant paths) ...We can see that '../text_analysis' points one directory above what you need. What would happen if we deleted one of the full stops, and instead wrote './text_analysis'? Output seems to be what we need:
# output: # ~/social-network-interest-engine/text_analysis # ~/social-network-interest-engine/social_networksBut we still have not imported the function. We know this because we reach the except part, which prints the paths. Looking at import, we can see that we have text_analysis.text_refinement. Do we really need to state the directory name if we already added it to the path? No, we do not. If we write
from text_refinement import camel_case_splitinstead, we find that the function has finally been imported. Following this logic, and assuming we wanted to leave text_analysis.text_refinement in import statement (for whatever reason), we could add path differently, too:
sys.path.insert(0, os.path.realpath('./'))Note, however, that this way of inserting the path is somewhat brittle. The starting location is the path from which you call python python_file.py If you navigated to different directory, you would need to adjust os.path.realpath accordingly. What you can do instead:
sys.path.insert(0, 'full/path/to/application/app/folder')Though this assumes that the directory/structure of your project will not change.
For a more in-depth overview of paths and imports, you can read more about importing stuff from different folders here, and if you prefer relative path imports, this is a useful thread. Of course, official documentation is also a good place to start.
更多推荐
发布评论