Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/python-2.7/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 模块从定期执行的相对文件夹导入_Python_Python 2.7 - Fatal编程技术网

Python 模块从定期执行的相对文件夹导入

Python 模块从定期执行的相对文件夹导入,python,python-2.7,Python,Python 2.7,假设我有以下结构: app/ __init__.py mod.py pkg/ __init__.py submod.py 其中,模块submod与mod具有相对导入,即: 我明白,如果我想以脚本的形式执行submod,我可以从app执行以下操作/ 但是我希望submod.py是一个可执行模块,我可以使用它在系统中的任何地方调用它 python/path/to/submod.py 我认为这已经解决了这个问题,也就是说,我认为在submod中进行任何相关

假设我有以下结构:

app/
   __init__.py
   mod.py

   pkg/
      __init__.py
      submod.py
其中,模块submod与mod具有相对导入,即:

我明白,如果我想以脚本的形式执行submod,我可以从app执行以下操作/

但是我希望submod.py是一个可执行模块,我可以使用它在系统中的任何地方调用它

python/path/to/submod.py

我认为这已经解决了这个问题,也就是说,我认为在submod中进行任何相关导入之前添加以下样板代码:

然后我可以回到常规的python/path/to/submod.py。然而,当我这样做时,我得到:

SystemError: Parent module 'app' not loaded, cannot perform relative import
为什么?

最后,我了解到一个解决方案是在submod中操纵sys.path,以便它可以看到mod1,然后执行常规导入mod1并避免相对导入。但如图所示,这是危险的,因为一个模块中对sys.path的任何更改都会传播到其他所有模块,所以一般来说,篡改sys.path不是一个好主意

有没有办法做到:

支持常规python/path/to/submod.py调用的相对导入 或

能够使用python/path/to/submod.py执行我的模块,而不必修改sys.path或PYTHONPATH ?该软件包不是pkg2;是app.pkg2。相应地设置包:

if __name__ = '__main__' and __package__ is None:
    __package__ = 'app.pkg2'
如果这不是问题所在,那么应用程序可能不在路径上。我所知道的最好的解决方案是通过移动应用程序或将其当前目录放在PYTHONPATH中,将其放在路径上,但如果您正在寻找一种方法,让应用程序中的模块彼此看到,而不让外部模块看到,我什么都不知道。它似乎很有用。

该软件包不是pkg2;是app.pkg2。相应地设置包:

if __name__ = '__main__' and __package__ is None:
    __package__ = 'app.pkg2'

如果这不是问题所在,那么应用程序可能不在路径上。我所知道的最好的解决方案是通过移动应用程序或将其当前目录放在PYTHONPATH中,将其放在路径上,但如果您正在寻找一种方法,让应用程序中的模块彼此看到,而不让外部模块看到,我什么都不知道。它似乎很有用。

正如PEP 366在您复制的样板文件之后明确指出的那样:

注意,只有当顶层包已经可以通过sys.path访问时,此样板文件才足够。需要额外的代码来操作sys.path,以便在顶层包不可导入的情况下直接执行

因此,假设您的代码如下所示:

if __name__ == "__main__" and __package__ is None:
    __package__ = "app.pkg"
from .. import mod
SystemError: Parent module 'app' not loaded, cannot perform relative import
您应该得到如下异常:

if __name__ == "__main__" and __package__ is None:
    __package__ = "app.pkg"
from .. import mod
SystemError: Parent module 'app' not loaded, cannot perform relative import
正如错误消息所暗示的,在进行任何相对导入之前,您需要以某种方式导入应用程序。这显然意味着你不能相对导入应用程序,所以你需要绝对导入它。有各种各样的黑客方法可以做到这一点,或者你可以按照政治公众人物的建议和munge sys.path解决所有隐含的问题。但除此之外,你不能这样做

这只是试图从包的中间运行脚本很困难的多个原因之一。这是有意的;如中所述:

Guido将包中运行的脚本视为反模式

有两种方法可以实现你想要的。首先,您已经开始工作了:只需将模块作为模块而不是脚本运行。PEP 366的主要目的就是让它发挥作用。另一种方法是将模块和脚本分成两部分。只需编写一个包装器,您就可以轻松完成这项工作

例如,假设submod.py看起来像这个愚蠢的玩具示例:

if __name__ == "__main__" and __package__ is None:
    __package__ = "app.pkg"
from .. import mod

def main(argv):
    print(argv)

if __name__ == '__main__':
    import sys
    main(sys.argv)
创建一个新文件,例如sub.py,作为包的同级文件:

import sys
import app.pkg.submod
app.pkg.submod.main(sys.argv)
现在,您可以在系统的任何位置运行sub.py。正如上面所说:

当程序启动时初始化时,此列表的第一项路径[0]是包含用于调用Python解释器的脚本的目录


由于该目录也是应用程序所在的目录,您保证能够绝对导入app.pkg.submod,这意味着submod将能够相对导入它想要的任何内容。

正如PEP 366在您复制的样板文件之后明确指出的那样:

注意,只有当顶层包已经可以通过sys.path访问时,此样板文件才足够。需要额外的代码来操作sys.path,以便在顶层包不可导入的情况下直接执行

因此,假设您的代码如下所示:

if __name__ == "__main__" and __package__ is None:
    __package__ = "app.pkg"
from .. import mod
SystemError: Parent module 'app' not loaded, cannot perform relative import
您应该得到如下异常:

if __name__ == "__main__" and __package__ is None:
    __package__ = "app.pkg"
from .. import mod
SystemError: Parent module 'app' not loaded, cannot perform relative import
正如错误消息所暗示的,在进行任何相对导入之前,您需要以某种方式导入应用程序。这显然意味着你不能相对导入应用程序,所以你需要绝对导入它。有各种各样的黑客方法可以做到这一点,或者你可以按照政治公众人物的建议和munge sys.path解决所有隐含的问题。但除此之外,你不能这样做

这只是试图从包的中间运行脚本很困难的多个原因之一。那就是我 意念性;如中所述:

Guido将包中运行的脚本视为反模式

有两种方法可以实现你想要的。首先,您已经开始工作了:只需将模块作为模块而不是脚本运行。PEP 366的主要目的就是让它发挥作用。另一种方法是将模块和脚本分成两部分。只需编写一个包装器,您就可以轻松完成这项工作

例如,假设submod.py看起来像这个愚蠢的玩具示例:

if __name__ == "__main__" and __package__ is None:
    __package__ = "app.pkg"
from .. import mod

def main(argv):
    print(argv)

if __name__ == '__main__':
    import sys
    main(sys.argv)
创建一个新文件,例如sub.py,作为包的同级文件:

import sys
import app.pkg.submod
app.pkg.submod.main(sys.argv)
现在,您可以在系统的任何位置运行sub.py。正如上面所说:

当程序启动时初始化时,此列表的第一项路径[0]是包含用于调用Python解释器的脚本的目录


由于该目录也是应用程序所在的目录,因此保证您能够绝对导入app.pkg.submod,这意味着submod将能够相对导入它想要的任何内容。

您可能需要注意在包层次结构中包含脚本:from。。import pkg1.mod1在2.6-7或3.x中都不是有效的导入语句;它应该给你一个SyntaxError,然后你就可以找到你要调试的问题了。如果将其更改为from..pkg1 import mod1,则会出现一个与导入相关的系统错误,但不是显示的错误。调试一个无法在我们看不见的代码中重现的问题是很困难的;你能给我们一个实际的例子来说明你的问题吗?还有…你使用的是哪种Python版本?谢谢@abarnert-我刚刚更新了OP来回答你的两个问题questions@user815423426:没有一种非黑客方式可以做到这一点……但有一种非常简单且完全非黑客的方式可以实现您可能真正需要的功能:将submod.py拆分为实际模块,以及位于仅导入子模块并调用其主函数的包旁边的脚本。您可能需要注意在包层次结构中包含脚本:from。。import pkg1.mod1在2.6-7或3.x中都不是有效的导入语句;它应该给你一个SyntaxError,然后你就可以找到你要调试的问题了。如果将其更改为from..pkg1 import mod1,则会出现一个与导入相关的系统错误,但不是显示的错误。调试一个无法在我们看不见的代码中重现的问题是很困难的;你能给我们一个实际的例子来说明你的问题吗?还有…你使用的是哪种Python版本?谢谢@abarnert-我刚刚更新了OP来回答你的两个问题questions@user815423426:没有一种非黑客方式可以做到这一点……但有一种非常简单且完全非黑客的方式可以实现您可能真正需要的功能:将submod.py拆分为实际的模块,以及位于仅导入子模块并调用其主函数的包旁边的脚本。发布的目录结构与错误消息不一致。抱歉。我打字太快了,没有复制。您发布的目录结构与错误消息不一致。抱歉。我打字太快了,没有抄写。