简体   繁体   English

Python导入,路径,目录和模块

[英]Python Imports, Paths, Directories & Modules

Let me start by saying I've done extensive research over the course of the past week and have not yet found actual answers to these questions - just some fuzzy answers that don't really explain what is going on. 首先让我说我已经对过去一周的过程进行了广泛的研究,但还没有找到这些问题的实际答案 - 只是一些模糊的答案并没有真正解释发生了什么。 If that's just cause I missed what I was looking for, I'm sorry - please just point me in the correct direction. 如果这只是因为我错过了我想要的东西,我很抱歉 - 请指出我正确的方向。

My directory structure is: 我的目录结构是:

TestProject/
    runtest*
    testpackage/
        __init__.py
        testmod.py
        testmod2.py
        testsubs/
            testsubmod.py

A couple notes: 几个笔记:

  • I'm using python2.7 on Ubuntu 我在Ubuntu上使用python2.7
  • I'm testing with bpython 我正在测试bpython
  • I'm running bpython from specific directories to test the way import behaves 我正在从特定目录运行bpython来测试导入行为的方式
  • I'm attempting to follow best practices. 我正在尝试遵循最佳做法。
  • This package is not installed, it's in a random dev directory 这个软件包没有安装,它在一个随机的dev目录中
  • This directory is not in the pythonpath 该目录不在pythonpath中
  • I have a single init .py in the package directory 我在包目录中有一个init .py
  • There are no init .py files in the nested directories 嵌套目录中没有init .py文件
  • The init .py file is empty init .py文件为空
  • testpackage/testmod.py contains TestModClass testpackage / testmod.py包含TestModClass
  • testpackage/testsubs/testsubmod.py contains TestSubModClass testpackage / testsubs / testsubmod.py包含TestSubModClass

Things I've observed: 我观察到的事情:

  • When I run bpython from TestProject/ import testpackage works 当我从TestProject / import testpackage运行bpython时
    • This does not import testpackage.testmod 这不会导入testpackage.testmod
    • I cannot access testpackage.testmod at all 我根本无法访问testpackage.testmod
  • When I run bpython from TestProject/ import testpackage.testmod fails 当我从TestProject / import运行bpython时, testpackage.testmod失败了
  • When I run bpython from TestProject/ from testpackage import testmod works 当我从testProject运行bpython / 从testpackage导入testmod工作
  • I can add code to init .py to explicitly import testmod.py, but not testsubs/testmod.py 我可以向init .py添加代码以显式导入testmod.py,但不能testubs / testmod.py
    • I don't think this is the correct way to do this, what if the user doesn't want to import that module? 我不认为这是正确的方法,如果用户不想导入该模块怎么办?
  • from testmod.py i can import testmod2, but not testpackage.testmod2 从testmod.py我可以导入testmod2,但不能导入testpackage.testmod2
    • This would be nice to do so that I can name my own modules with overlapping names with STL or twisted (such as testpackage.logging) without causing errors (it sucks to have to name my own modules crap like customerlogging, instead of just mypackage.logging) 这样做很好,我可以使用STL或扭曲的名称(例如testpackage.logging)命名我自己的模块,而不会导致错误(很糟糕的是必须命名我自己的模块废话,如customerlogging,而不仅仅是mypackage。日志记录)

And the questions: 问题是:

  1. Does python deal differently with imports on packages & modules that exist in the pythonpath than when you are trying to import from your current directory? python路径中存在的包和模块上的导入与您尝试从当前目录导入时的python处理方式不同吗?
  2. Why doesn't import testpackage give me access to testpackage.testmod? 为什么不导入testpackage让我访问testpackage.testmod? When I import os, I can then access os.path (etc). 当我导入操作系统时,我可以访问os.path(etc)。
  3. With a package, should I stick to using a single init .py in the base directory, or should I be nesting them in subsequent directories? 使用包,我应该坚持在基目录中使用单个init .py,还是应该将它们嵌套在后续目录中?
  4. How can I import a module specifying the package name? 如何导入指定包名称的模块? IE from testmod.py, I would like to import testpackage.testmod2 rather than just testmod2. 来自testmod.py的IE,我想导入testpackage.testmod2而不仅仅是testmod2。
  5. What is the proper way to import submodules from the subsubs directory? 从subsubs目录导入子模块的正确方法是什么?
    1. The only solution I see is to append that directory to the pythonpath from init .py, but I don't know if that's the correct way. 我看到的唯一解决方案是将该目录从init .py附加到pythonpath,但我不知道这是否正确。

Thanks in advance. 提前致谢。

First off, you will find all the information you need in section 6 of The Python Tutorial . 首先,您将在The Python Tutorial的第6部分找到所需的所有信息。


(1) Does python deal differently with imports on packages & modules that exist in the pythonpath than when you are trying to import from your current directory? (1)python路径中存在的包和模块上的python与您尝试从当前目录导入时的处理方式不同吗?

No, it doesn't. 不,它没有。 Actually, Python always searches sys.path when importing modules. 实际上,Python在导入模块时总是搜索sys.path Modules in the current directory are only found since sys.path contains an entry with the empty string, meaning the current directory. 仅找到当前目录中的模块,因为sys.path包含带有空字符串的条目,表示当前目录。


(2) Why doesn't import testpackage give me access to testpackage.testmod ? (2)为什么不import testpackage让我访问testpackage.testmod When I import os , I can then access os.path (etc). 当我导入os ,我可以访问os.path (etc)。

For efficiency, import testpackage only loads testpackage/__init__.py . 为了提高效率, import testpackage只加载testpackage/__init__.py If you need testpackage.testmod , you have to explicitely import it: 如果你需要testpackage.testmod ,你必须明确地导入它:

import testpackage   # Just imports testpackage, not testpackage.testmod!
import testpackage.testmod   # Import *both* testpackage and testpackage.testmod!

If you always want to export testmod , import it within __init__.py , this is what os ( os/__init__.py ) does. 如果你总是想导出testmod ,在__init__.py导入它,这就是osos/__init__.py )所做的。 This way, testpackage.testmod is always available implicitely if you import testpackage . 这样,如果导入testpackagetestpackage.testmod总是隐含可用。

Since Python is cross-platform, there is actually no way to consistently and automatically load modules in a directory, because some filesystems are case-insensitive (Windows!). 由于Python是跨平台的,因此实际上无法在目录中一致地自动加载模块,因为某些文件系统不区分大小写(Windows!)。 Python would not know whether to load os/path.py as os.path or os.Path , etc. Python不知道是否将os/path.py加载为os.pathos.Path等。


(3) With a package, should I stick to using a single __init__.py in the base directory, or should I be nesting them in subsequent directories? (3)对于一个包,我应该坚持在基目录中使用单个__init__.py ,还是应该将它们嵌套在后续目录中?

You always need an __init__.py for each subpackage. 每个子包总是需要__init__.py There were discussions on dropping this requirement, but it was decided to keep it as it is. 有关于放弃这一要求的讨论,但决定保持原样。


(4) How can I import a module specifying the package name? (4)如何导入指定包名称的模块? IE from testmod.py , I would like to import testpackage.testmod2 rather than just testmod2 . 来自testmod.py IE,我想导入testpackage.testmod2而不仅仅是testmod2

This should work. 这应该工作。 Just ensure that you run the code from the top-level directory. 只需确保从顶级目录运行代码。 If the current directory is testpackage , testmod does not know that it's in a package. 如果当前目录是testpackage ,则testmod不知道它在包中。

The preferred way is to use relative intra-package imports, though: 但首选的方法是使用相对的包内导入:

from . import testmod2

This prevents name clashes if there is a global module named testmod2 and enables you to use the names of well-known modules within your package without problems. 如果存在名为testmod2的全局模块,则可以防止名称冲突,并且可以使用包中的已知模块的名称而不会出现问题。


(5) What is the proper way to import submodules from the subsubs directory? (5)从subsubs目录导入子模块的正确方法是什么? The only solution I see is to append that directory to the pythonpath from __init__.py , but I don't know if that's the correct way. 我看到的唯一解决方案是将该目录从__init__.py附加到pythonpath,但我不知道这是否正确。

No, don't do that! 不,不要那样做! Never, ever put a directory to sys.path when one of it's parent directories already is in sys.path ! 永远不要把一个目录下sys.path当它的一个父目录已经在sys.path This could cause your modules to be loaded twice, which is a bad thing! 这可能导致您的模块加载两次,这是一件坏事!

Usually you should be able to load modules from subpackages using absolute or relative imports: 通常,您应该能够使用绝对或相对导入从子包加载模块:

import testpackage.testsubs.testsubmod
from testpackage.testsubs import testsubmod
from .testsubs import testsubmod

Just make sure to create a __init__.py within testsubs/ ! 只需确保在testsubs/创建__init__.py

  1. No. The current directory is just added to PYTHONPATH. 不。当前目录刚刚添加到PYTHONPATH。
  2. First, you need a __init__.py in there. 首先,你需要一个__init__.py。 Second, os.path comes because os is importing os.path. 其次,os.path是因为os正在导入os.path。
  3. You need a __init__.py in every directory, also in the one containing the testpackage directory. 每个目录中需要__init__.py,也包含testpackage目录。
  4. In the package's __init__.py, import the modules you wish to provide. 在包的__init__.py中,导入您要提供的模块。
  5. from sub1.sub2 import submodule 来自sub1.sub2 import子模块
    1. No, if the top-most directory is on PYTHONPATH, and this and the subdirectories have their __init__.py, this is all you need to import from any of the subdirectories. 不,如果最顶层的目录在PYTHONPATH上,并且这个和子目录有__init__.py,那么您只需要从任何子目录导入。

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

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