<p>Python需要知道<code>foo</code>所在的目录才能导入它<code>sys.path</code>列出python将在其中搜索的目录</p>
<p>当你安装一个软件包时,安装程序会担心这样做——通常是将模块放在一个已知的目录中,或者将安装程序包路径添加到<code>sys.path</code></p>
<p>当您运行脚本时,python会自动将该脚本的路径添加到<code>sys.path</code>,因此当您运行<code>main.py</code>时,您会发现<code>foo</code></p>
<p><em>如何作为模块运行<code>__main__</code></em></p>
<p>一个选项是使包可安装(setup.py、wheels等),并使用开发模式(<a href="https://stackoverflow.com/questions/30306099/pip-install-editable-vs-python-setup-py-develop">"pip install editable ./" vs "python setup.py develop"</a>进行一些讨论)。这就是我在开发我计划提供给他人的东西时所做的</p>
<p>另一种方法是将您的目录添加到PYTHONPATH,甚至在您运行该程序时。在linux上,这将是</p>
<pre><code>PYTHONPATH=path/to/fooproject:$PYTHONPATH python foo/quux/corge.py
</code></pre>
<p>还有一个,我也这么做了,就是破解模块本身的路径<code>__file__</code>给出相对于当前工作目录的文件名,您知道自己在包层次结构中的位置有多深。因此,您只需将<code>__file__</code>设为绝对值,并去掉几个目录名即可</p>
<p>柯基·皮</p>
<pre><code>import sys
import os
if __name__ == "__main__":
# I'm two levels deep in the package so package directory is
packagedir = os.path.abspath(os.path.join(os.path.dirname(__file__),
"..", ".."))
sys.path.insert(0, packagedir)
import foo
</code></pre>
<p>最后,一开始不要这样做。当您将<code>corge.py</code>作为脚本运行时,它会得到一个不同于作为模块导入的<code>__main__</code>的命名空间。它的全局变量/类/函数被加载两次,根据您是通过<code>__main__</code>名称空间还是<code>foo.bar.corge</code>调用它们,可以得到不同的变量/类/函数</p>
<p>最好是将任何您想放在<code>corge.py</code>中的内容放在一个main中,使它们成为单独的脚本。例如,您可以将<code>def main()</code>添加到模块中。在<code>main.py</code>中,您可以添加一个选项<code> run foo.bar.corge</code>,告诉main导入<code>corge.py</code>并运行其<code>main()</code><a href="https://docs.python.org/3/library/argparse.html#sub-commands" rel="nofollow noreferrer">^{<cd21>} subcommands</a>可用于此</p>