<blockquote>
<p>unfortunately, this module needs to be inside the package, and it also
needs to be runnable as a script, sometimes. Any idea how I could
achieve that?</p>
</blockquote>
<p>像这样的布局很常见。。。</p>
<pre><code>main.py
mypackage/
__init__.py
mymodule.py
myothermodule.py
</code></pre>
<p>…像这样的<code>mymodule.py</code>。。。</p>
<pre><code>#!/usr/bin/env python3
# Exported function
def as_int(a):
return int(a)
# Test function for module
def _test():
assert as_int('1') == 1
if __name__ == '__main__':
_test()
</code></pre>
<p>…像这样的<code>myothermodule.py</code>。。。</p>
<pre><code>#!/usr/bin/env python3
from .mymodule import as_int
# Exported function
def add(a, b):
return as_int(a) + as_int(b)
# Test function for module
def _test():
assert add('1', '1') == 2
if __name__ == '__main__':
_test()
</code></pre>
<p>…还有像这样的<code>main.py</code>。。。</p>
<pre><code>#!/usr/bin/env python3
from mypackage.myothermodule import add
def main():
print(add('1', '1'))
if __name__ == '__main__':
main()
</code></pre>
<p>…当您运行<code>main.py</code>或<code>mypackage/mymodule.py</code>时工作正常,但由于相对导入,<code>mypackage/myothermodule.py</code>失败。。。</p>
<pre><code>from .mymodule import as_int
</code></pre>
<p>你应该用的方式是。。。</p>
<pre><code>python3 -m mypackage.myothermodule
</code></pre>
<p>……但它有点冗长,不能很好地与<code>#!/usr/bin/env python3</code>这样的shebang行混合。</p>
<p>对于这种情况,假设名称<code>mymodule</code>是全局唯一的,最简单的解决方法是避免使用相对导入,而只使用。。。</p>
<pre><code>from mymodule import as_int
</code></pre>
<p>…但是,如果它不是唯一的,或者包结构更复杂,则需要将包含包目录的目录包含在<code>PYTHONPATH</code>中,并按如下方式执行。。。</p>
<pre><code>from mypackage.mymodule import as_int
</code></pre>
<p>…或者如果你想让它“开箱即用”的话,你可以先用这个来替换代码中的<code>PYTHONPATH</code>。。。</p>
<pre><code>import sys
import os
PACKAGE_PARENT = '..'
SCRIPT_DIR = os.path.dirname(os.path.realpath(os.path.join(os.getcwd(), os.path.expanduser(__file__))))
sys.path.append(os.path.normpath(os.path.join(SCRIPT_DIR, PACKAGE_PARENT)))
from mypackage.mymodule import as_int
</code></pre>
<p>这是一种痛苦,但有一个线索可以解释为什么在某个吉多·范·罗森写的<a href="http://mail.python.org/pipermail/python-3000/2007-April/006793.html" rel="noreferrer">an email</a>中。。。</p>
<blockquote>
<p>I'm -1 on this and on any other proposed twiddlings of the <code>__main__</code>
machinery. The only use case seems to be running scripts that happen
to be living inside a module's directory, which I've always seen as an
antipattern. To make me change my mind you'd have to convince me that
it isn't.</p>
</blockquote>
<p>在包中运行脚本是否是反模式是主观的,但我个人认为,在包含一些自定义wxPython小部件的包中,它确实很有用,因此我可以为任何源文件运行脚本,以显示仅包含该小部件的<code>wx.Frame</code>,用于测试目的。</p>