所以我使用的是同事设置的模板,作为python的新手,我可能会遗漏一些非常明显的东西.
主目录有init文件,它有一个生成错误的主python文件所需的模块.
同事使用:
from . import X
Run Code Online (Sandbox Code Playgroud)
其中X是模块,但是当将此(以及填充的init文件)复制到我自己的目录时,它会生成此错误:
ValueError:在非包中尝试相对导入
从谷歌和SO我收集到这是完美的和合乎逻辑的所以我想知道,作为一个新手,我错过了什么.
在PEP 366 -主模块显式相对导入中引入了模块范围变量__package__
以允许在子模块中显式相对导入,有以下摘录:
当主模块由其文件名指定时,该
__package__
属性将设置为None
. 为了在直接执行模块时允许相对导入,在第一个相对导入语句之前需要类似于以下的样板:Run Code Online (Sandbox Code Playgroud)if __name__ == "__main__" and __package__ is None: __package__ = "expected.package.name"
请注意,仅当顶级包已经可以通过
sys.path
. 需要额外的操作代码sys.path
才能直接执行工作,而无需导入顶级包。这种方法也有与使用兄弟模块的绝对导入相同的缺点——如果脚本被移动到不同的包或子包,样板将需要手动更新。它的优点是每个文件只需进行一次此更改,而不管相关导入的数量如何。
我尝试在以下设置中使用此样板:
目录布局:
foo
??? bar.py
??? baz.py
Run Code Online (Sandbox Code Playgroud)
bar.py 子模块的内容:
if __name__ == "__main__" and __package__ is None:
__package__ = "foo"
from . import baz
Run Code Online (Sandbox Code Playgroud)
当从文件系统执行子模块 bar.py 时,样板工作(PYTHONPATH
修改使包 foo/ 可访问sys.path
):
PYTHONPATH=$(pwd) python3 foo/bar.py
Run Code Online (Sandbox Code Playgroud)
当从模块命名空间执行子模块 bar.py 时,样板也可以工作:
python3 -m foo.bar
Run Code Online (Sandbox Code Playgroud)
但是,以下替代样板在这两种情况下都与 bar.py 子模块的内容一样有效:
if __package__:
from …
Run Code Online (Sandbox Code Playgroud) 我在那里尝试过的每个调试器都需要一个源文件来调试。然而Python并不总是这样工作。
我有一个模块,它是一个文件夹,里面有__init__.py
和__main__.py
文件等,我通常这样执行:
$ cd /parent/folder
$ python3 -m module_folder --help
Run Code Online (Sandbox Code Playgroud)
如果我不使用-m
,相对导入就会失败。如果我只是将文件夹传递给pudb
,pdb
和其他人,调试器将失败:
$ cd /parent/folder
$ python3 -m pdb module_folder
Traceback (most recent call last):
File "/usr/lib64/python3.3/pdb.py", line 1658, in main
pdb._runscript(mainpyfile)
File "/usr/lib64/python3.3/pdb.py", line 1536, in _runscript
with open(filename, "rb") as fp:
IsADirectoryError: [Errno 21] Is a directory: 'module_folder'
Uncaught exception. Entering post mortem debugging
Running 'cont' or 'step' will restart the program
> /usr/lib64/python3.3/pdb.py(1536)_runscript()
-> with open(filename, "rb") as …
Run Code Online (Sandbox Code Playgroud) 下面这行代码在 Python 3 中起什么作用?
>>> from . import *
Run Code Online (Sandbox Code Playgroud)
它不输出任何内容,我在 Python 3.7.3 中看到的唯一变化如下:
>>> '__warningregistry__' in locals()
False
>>> from . import *
>>> '__warningregistry__' in locals()
True
>>> locals()['__warningregistry__']
{'version': 0}
Run Code Online (Sandbox Code Playgroud)
这可能是警告模块的一部分,表示在某处有一个未打印的警告,但文档仅提到了模块中的一个变量 。__warningregistry__
warnings
该文档解释了如何from . import foo
工作以及如何from bar import *
工作,但我找不到任何有关from . import *
. 人们可能期望所有名称都__init__.py
加载到当前名称空间中(就像from bla import *
一样bla.py
),但情况似乎并非如此,而且在__name__ == '__main__'
(脚本和终端)时也没有意义。
Python 2 的行为与我的预期更加相似:
>>> # Python 2.7.16
>>> from …
Run Code Online (Sandbox Code Playgroud) 我的文件夹结构如下
\n./fff\n\xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 __init__.py\n\xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 fg\n\xe2\x94\x82\xc2\xa0\xc2\xa0 \xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 __init__.py\n\xe2\x94\x82\xc2\xa0\xc2\xa0 \xe2\x94\x94\xe2\x94\x80\xe2\x94\x80 settings\n\xe2\x94\x82\xc2\xa0\xc2\xa0 \xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 __init__.py\n\xe2\x94\x82\xc2\xa0\xc2\xa0 \xe2\x94\x94\xe2\x94\x80\xe2\x94\x80 settings.py\n\xe2\x94\x94\xe2\x94\x80\xe2\x94\x80 obng\n \xe2\x94\x94\xe2\x94\x80\xe2\x94\x80 test.py\n
Run Code Online (Sandbox Code Playgroud)\n我想将 fg/settings 中的 settings.py 作为模块导入到 test.py 中
\n我已经添加了该行
\n从 ..fg.settings 导入设置
\n但是当我运行它时,它给了我以下错误
\n回溯(最近一次调用最后):\n文件“/mnt/d/Repos/fff/obng/test.py”,第 1 行,位于 \nfrom ..fg.settings 导入设置\nImportError:尝试在没有已知父项的情况下进行相对导入包裹
\n根据https://docs.python.org/3/reference/import.html#package-relative-imports支持这种相对导入方式
\n我在这里做错了什么?
\n是的,有类似的问题,但他们没有回答我的问题.我的目录结构如下,所有__init__.py文件都是空白的.
Package/
__init__.py
sub_package1/
__init__.py
file1.py
sub_package2/
__init__.py
file2.py
Run Code Online (Sandbox Code Playgroud)
在file2.py
我有以下代码:
from ..sub_package1 import file1
Run Code Online (Sandbox Code Playgroud)
我得到上面提到的错误,
ValueError: attempted relative import beyond top-level package
Run Code Online (Sandbox Code Playgroud)
有许多scikit-learn软件包可以执行类似的导入,并且适用于它们.
引发错误的命令:
Package/
python /path/to/Package/sub_package2/file2.py
我花了过去一小时的时间来浏览Google和SO.很抱歉添加另一个,但没有一个答案对我有用.
我的目录结构/VM/repo/project
是:
__init__.py
scripts/
getSomething.py
__init__.py
classes/
project.py
db.py
__init__.py
Run Code Online (Sandbox Code Playgroud)
====================
getSomething.py
from ..classes import project
from ..classes import db
Run Code Online (Sandbox Code Playgroud)
====================
project.py
class PROJECT:
def __init__(self):
stuff
Run Code Online (Sandbox Code Playgroud)
====================
db.py
class DB:
def __init__(self):
stuff
Run Code Online (Sandbox Code Playgroud)
====================
当我试图跑
python getSomething.py
我收到了错误
Traceback(最近一次调用最后一次):
在<module>中的文件"scripts/getSomething.py",第4行
来自..classes导入项目
ValueError:在非包中尝试相对导入
我在这里错过了什么?
我的包结构:
root_pkg
root_pkg/__init__.py # empty
root_pkg/game
root_pkg/game/__init__.py # empty
root_pkg/game/game1.py
root_pkg/utils
root_pkg/utils/__init__.py # empty
root_pkg/utils/lib.py
Run Code Online (Sandbox Code Playgroud)
root_pkg/game/game1.py
包含:
"""File root_pkg/game/game1.py"""
from ..utils import lib
Run Code Online (Sandbox Code Playgroud)
不会发出任何错误
然而,在 pycharm 中运行它:
C:\_\Python363-64\python.exe C:/Dropbox/eclipse_workspaces/python/test_imports/root_pkg/game/game1.py
Traceback (most recent call last):
File "C:/Dropbox/eclipse_workspaces/python/test_imports/root_pkg/game/game1.py", line 3, in <module>
from ..utils import lib
ValueError: attempted relative import beyond top-level package
Process finished with exit code 1
Run Code Online (Sandbox Code Playgroud)
但是,内容和源路径被添加到运行配置中的 python 路径:
那么为什么 Pycharm 不能运行这个呢?它不应该将项目文件夹添加到 PYTHONPATH 吗?使用正确的导入样式吗?
编辑:更改运行配置中的工作目录会C:\Dropbox\eclipse_workspaces\python\test_imports\
导致相同的错误:
C:\_\Python363-64\python.exe C:/Dropbox/eclipse_workspaces/python/test_imports/root_pkg/game/game1.py
Traceback (most recent call last):
File "C:/Dropbox/eclipse_workspaces/python/test_imports/root_pkg/game/game1.py", line 3, …
Run Code Online (Sandbox Code Playgroud) python ×8
python-3.x ×3
import ×2
boilerplate ×1
command-line ×1
debugging ×1
module ×1
package ×1
pudb ×1
pycharm ×1