简体   繁体   English

从目录中的其他路径运行python应用程序并导入模块

[英]Running python application and importing module from a different path within directory

For reference I've looked at the following links. 作为参考,我查看了以下链接。

I understand that I'm doing is wrong and I'm trying to avoid relative path and changing things in via sys.path as much as possible, though if those are my only options, please help me come up with a solution. 我知道我在做错了,我试图避免相对路径,并尽可能通过sys.path更改,尽管如果这是我唯一的选择,请帮助我提出解决方案。

Note, here is an example of my current working directory structure. 注意,这是我当前工作目录结构的示例。 I think I should add a little more context. 我想我应该再添加一些背景信息。 I started off adding __init__.py to every directory so they would be considered packages and subpackages, but I'm not sure that is what I actually want. 我开始将__init__.py添加到每个目录中,以便将它们视为软件包和子软件包,但是我不确定那是我真正想要的。

myapp/
    pack/
        __init__.py
        helper.py
    runservice/
        service1/
             Dockerfile
        service2/
            install.py
            Dockerfile

The only packages I will be calling exist in pack/ directory, so I believe that should be the only directory considered a package by python. 我将要调用的唯一软件包位于pack/目录中,因此我认为这应该是python认为是软件包的唯一目录。

Next, the reason why this might get a little tricky, ultimately, this is just a service that builds various different containers. 接下来,之所以会变得有些棘手,归根结底,这仅仅是一个构建各种不同容器的服务。 Where the entrypoints will live in python service*/install.py where I cd into the working directory of the script. 凡入口点必住在蟒蛇service*/install.py ,我cd到脚本的工作目录。 The reason for this, I don't want container1 (service1) to know about the codebase in service2 , as its irrelevant I would like and the code to be separated. 这样做的原因是,我不想让container1 (service1)知道service2的代码库,因为我不希望它与代码分离。

But, by running install.py , I need to be able to do: from pack.helper import function but clearly I am doing something wrong. 但是,通过运行install.py ,我需要能够做到: from pack.helper import function但显然我做错了什么。

Can someone help me come up with a solution, so I can leave my entrypoint to my container as cd service2 , python install.py . 有人可以帮我提出解决方案,因此可以将我的入口点保留为cd service2python install.py到我的容器中。

Another important thing to note, within the script I have logic like: 需要注意的另一件重要事情是,在脚本中,我有如下逻辑:

if not os.path.isdir(os.path.expanduser(tmpDir))

I am hoping any solution we come up with, will not affect the logic here? 我希望我们能提出任何解决方案,不会影响这里的逻辑吗?

I apologize for the noob question. 对于菜鸟问题​​,我深表歉意。

EDIT: 编辑:

Note, II think I can do something like 注意,我认为我可以做类似的事情

sys.path.append(os.path.join(os.path.dirname(__file__), '..'))

But as far as I understand, that is bad practice.... 但是据我了解,这是一种不好的做法。

Fundamentally what you've described is a supporting library that goes with a set of applications that run on top of it. 从根本上讲,您所描述的是一个支持库,该库带有在其上运行的一组应用程序。 They happen to be in the same repository (a "monorepo") but that's okay. 它们恰好位于同一个存储库中(“ monorepo”),但这没关系。

The first step is to take your library and package it up like a normal Python library would be. 第一步是获取您的库并将其打包,就像普通的Python库一样。 The Python Packaging User Guide has a section on Packaging and distributing projects , which is mostly relevant; Python打包用户指南》中有一个关于打包和分发项目的部分 ,该部分最为相关。 though you're not especially interested in uploading the result to PyPI. 尽管您对将结果上传到PyPI并不特别感兴趣。 You at the very least need the setup.py file described there. 您至少需要那里描述的setup.py文件。

With this reorganization you should be able to do something like 通过这种重组,您应该能够执行以下操作

$ ls pack
pack/  setup.py
$ ls pack/pack
__init__.py  helper.py
$ virtualenv vpy
$ . vpy/bin/activate
(vpy) $ pip install -e ./pack

The last two lines are important: in your development environment they create a Python virtual environment , an isolated set of packages, and then install your local library package into it. 最后两行很重要:在您的开发环境中,它们创建一个Python 虚拟环境 ,一组隔离的软件包,然后将本地库软件包安装到其中。 Still within that virtual environment, you can now run your scripts 仍然在该虚拟环境中,您现在可以运行脚本

(vpy) $ cd runservice/service2
(vpy) $ ./install.py

Your scripts do not need to modify sys.path ; 您的脚本不需要修改sys.path ; your library is installed in an "expected" place. 您的库安装在“预期”的位置。

You can and should do live development in this environment. 您可以并且应该在这种环境下进行实时开发。 pip install -e makes the virtual environment's source code for whatever's in pack be your actual local source tree. pip install -e使虚拟环境的源代码(无论pack是什么)成为您的实际本地源树。 If service2 happens to depend on other Python libraries, listing them out in a requirements.txt file is good practice. 如果service2碰巧依赖于其他Python库,则将它们列出在requirements.txt文件中是一个好习惯。

Once you've migrated everything into the usual Python packaging scheme, it's straightforward to transplant this into Docker. 一旦将所有内容迁移到常规的Python打包方案中,就可以将其轻松移植到Docker中。 The Docker image here plays much the same role as a Python virtual environment, in that it has an isolated Python installation and an isolated library tree. 此处的Docker映像与Python虚拟环境的作用几乎相同,因为它具有隔离的Python安装和隔离的库树。 So a Dockerfile for this could more or less look like 因此,与此相关的Dockerfile或多或少看起来像

FROM python:2.7

# Copy and install the library
WORKDIR /pack
COPY pack/ ./
RUN pip install .

# Now copy and install the application
WORKDIR /app
COPY runservice/service2/ ./
# RUN pip install -r requirements.txt

# Set standard metadata to run the application
CMD ["./install.py"]

That Dockerfile depends on being run from the root of your combined repository tree 该Dockerfile取决于从组合的存储库树的根目录运行

sudo docker build -f runservice/service2/Dockerfile -t me/service2 .

A relevant advanced technique is to break this up into separate Docker images. 一种相关的高级技术是将其分解为单独的Docker映像。 One contains the base Python plus your installed library, and the per-application images build on top of that. 其中一个包含基本的Python以及已安装的库,每个应用程序的映像均基于该库构建。 This avoids reinstalling the library multiple times if you need to build all of the applications, but it also leads to a more complicated sequence with multiple docker build steps. 如果您需要构建所有应用程序,这避免了多次重新安装该库,但是这也会导致具有多个docker build步骤的序列更加复杂。

# pack/Dockerfile
FROM python2.7
WORKDIR /pack
COPY ./ ./
RUN pip install .
# runservice/service2/Dockerfile
FROM me/pack
WORKDIR /app
COPY runservice/service2/ ./
CMD ["./install.py"]
#!/bin/sh
set -e
(cd pack && docker build -t me/pack .)
(cd runservice/service2 && docker build -t me/service2 .)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM