任何人都可以解释python的相对进口吗?

时间:2009-12-16 23:27:06

标签: python

我不能为我的生活让python的相对导入工作。我创建了一个不起作用的简单示例:

目录结构是:

/__init__.py
/start.py
/parent.py
/sub/__init__.py
/sub/relative.py

/start.py仅包含:import sub.relative

/sub/relative.py仅包含from .. import parent

所有其他文件都是空白的。

在命令行上执行以下操作时:

$ cd /
$ python start.py

我明白了:

Traceback (most recent call last):
  File "start.py", line 1, in <module>
    import sub.relative
  File "/home/cvondrick/sandbox/sub/relative.py", line 1, in <module>
    from .. import parent
ValueError: Attempted relative import beyond toplevel package

我正在使用Python 2.6。为什么会这样?如何使这个沙盒示例工作?

3 个答案:

答案 0 :(得分:131)

您正从包“sub”导入。即使存在start.py__init__.py本身也不在包中。

您需要从parent.py上的一个目录启动您的程序:

./start.py

./pkg/__init__.py
./pkg/parent.py
./pkg/sub/__init__.py
./pkg/sub/relative.py

使用start.py

import pkg.sub.relative

现在pkg是顶级包,您的相对导入应该有效。


如果您想坚持当前的布局,可以使用import parent。因为您使用start.py来启动解释器,所以start.py所在的目录位于您的python路径中。 parent.py作为一个单独的模块存在于那里。

如果您没有将任何内容导入目录树中的脚本,您也可以安全地删除顶级__init__.py

答案 1 :(得分:27)

如果您要直接致电relative.py,即如果您真的想从顶级模块导入,则必须将其明确添加到sys.path列表中。 以下是它应该如何工作:

# Add this line to the beginning of relative.py file
import sys
sys.path.append('..')

# Now you can do imports from one directory top cause it is in the sys.path
import parent

# And even like this:
from parent import Parent

如果您认为上述内容可能导致某种不一致,则可以使用此代码:

sys.path.append(sys.path[0] + "/..")

sys.path[0]指的是从中运行入口点的路径。

答案 2 :(得分:1)

在python3中进行检查:

# -------------
# Build Sources
# -------------
FROM node:10-alpine as builder

# Install additional git and openssh dependencies and make sure GitLab domain is accepted by SSH
RUN apk add --no-cache openssh git curl \
  && mkdir /root/.ssh/ \
  && touch /root/.ssh/known_hosts \
  && ssh-keyscan gitlab.com github.com >> /root/.ssh/known_hosts

WORKDIR /app

# Install app dependencies
RUN npm i -g typescript --no-cache --silent
COPY package*.json ./
RUN npm ci --only=production --silent

# Copy sources and build
COPY . .
RUN npm run build

# ----------------
# Production Image
# ----------------
FROM node:10-alpine
RUN apk add --no-cache curl

WORKDIR /app
COPY --from=builder /app/node_modules /app/node_modules
COPY --from=builder /app/dist /app/dist
COPY . .

USER node
CMD ["node", "dist/index.js"]

示例1

python -V
Python 3.6.5

如果我们这样运行(只是确保PYTHONPATH为空):

.
├── parent.py
├── start.py
└── sub
    └── relative.py

- start.py
import sub.relative

- parent.py
print('Hello from parent.py')

- sub/relative.py
from .. import parent

输出:

PYTHONPATH='' python3 start.py

如果我们更改Traceback (most recent call last): File "start.py", line 1, in <module> import sub.relative File "/python-import-examples/so-example-v1/sub/relative.py", line 1, in <module> from .. import parent ValueError: attempted relative import beyond top-level package 中的导入

sub/relative.py

如果我们这样运行它:

- sub/relative.py
import parent

输出:

PYTHONPATH='' python3 start.py

示例2:

Hello from parent.py

运行方式:

.
├── parent.py
└── sub
    ├── relative.py
    └── start.py

- parent.py
print('Hello from parent.py')

- sub/relative.py
print('Hello from relative.py')

- sub/start.py
import relative
from .. import parent

输出:

PYTHONPATH='' python3 sub/start.py

如果我们更改Hello from relative.py Traceback (most recent call last): File "sub/start.py", line 2, in <module> from .. import parent ValueError: attempted relative import beyond top-level package 中的导入,

sub/start.py

运行方式:

- sub/start.py
import relative
import parent

输出:

PYTHONPATH='' python3 sub/start.py

运行方式:

Hello from relative.py
Traceback (most recent call last):
  File "sub/start.py", line 3, in <module>
    import parent
ModuleNotFoundError: No module named 'parent'

输出:

PYTHONPATH='.' python3 sub/start.py

另外,最好使用从根文件夹导入,即:

Hello from relative.py
Hello from parent.py

运行方式:

- sub/start.py
import sub.relative
import parent

输出:

PYTHONPATH='.' python3 sub/start.py