我不能为我的生活让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。为什么会这样?如何使这个沙盒示例工作?
答案 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