简体   繁体   English

在python包中使用另一个文件中的类并在__init __()中发生冲突

[英]Using class from another file in python package and conflicts in __init__()

I'm writing a python package (python 3.6) and have the following directory structure: 我正在编写一个python包(python 3.6),并具有以下目录结构:

package/
|  __init__.py
|  fileA.py
|  fileB.py
|  tests/
|  |  __init__.py
|  |  test_classA.py
|  |  test_classB.py

Setup 设定

My files have the following contents: 我的文件具有以下内容:

# package/fileA.py
from package import ClassB

def ClassA:
    def __init__(self):
        self.my_ClassB = ClassB()

- --

# package/fileB.py
def ClassB:
    def __init__(self):
        self.foo = "bar"

- --

# package/tests/test_classB.py
from package import ClassB

# <performs some unit tests here>

- --

# package/tests/test_classA.py
from package import ClassA

# <performs some unit tests here>

- --

# package/__init__.py
from .fileA import ClassA
from .fileB import ClassB

Circular importing 循环进口

When I ran python test_classB.py , I get the following traceback error showing that I have circular import statements, which are not allowed by python. 当我运行python test_classB.py ,出现以下回溯错误,表明我具有循环导入语句,这是python不允许的。 Note - the package is not literally called package and I have edited the Traceback to match the toy example above. 注意-该包实际上不是package ,我已经编辑了Traceback以匹配上面的玩具示例。

Traceback (most recent call last):
  File "package/tests/test_classB.py", line 2, in <module>
    from package import ClassB
  File "/anaconda/lib/python3.5/site-packages/package/__init__.py", line 2, in <module>
    from .fileA import ClassA
  File "/anaconda/lib/python3.5/site-packages/package/merparse.py", line 2, in <module>
    from package import ClassB
ImportError: cannot import name 'ClassB'

Correcting the error 更正错误

However, when I remove those two lines in my package/__init__.py file: 但是,当我删除package/__init__.py文件中的package/__init__.py

# package/__init__.py
from .fileA import ClassA
from .fileB import ClassB

...and I change the import method for package/fileA.py : ...然后更改package/fileA.py的导入方法:

# package/fileA.py
from package.fileB import ClassB

def ClassA:
    def __init__(self):
        self.my_ClassB = ClassB()

... package/tests/test_classB.py runs correctly. ... package/tests/test_classB.py正确运行。

My Question 我的问题

My question is: How can I keep the one file: one class structure in my files and import with from package import ClassA instead of having to import with from package.fileA import ClassA ? 我的问题是:如何保存一个文件:文件中的一个类结构,然后from package import ClassA导入,而不必from package.fileA import ClassA

In my package I would like to import classes from other files, but don't know how to get around circular importing. 在我的程序包中,我想从其他文件导入类,但是不知道如何避免循环导入。

Edit: Solution 编辑:解决方案

Thanks to @mirandak and @martin-kalcok below for their help. 感谢下面的@mirandak和@ martin-kalcok的帮助。

The only file that I had to edit was fileA.py to not refer to the package name in the import statement. 我唯一需要编辑的文件是fileA.py ,以免在import语句中引用程序包名称。

# package/fileA.py
from .fileB import ClassB

def ClassA:
    def __init__(self):
        self.my_ClassB = ClassB()

The package/__init__.py file still contains import statements in case I want to import the package from other scripts in the future that I don't couple with the package. package/__init__.py文件仍然包含import语句,以防将来我不想从其他脚本中导入该脚本时从其他脚本中导入该软件包。

# package/__init__.py
from .fileA import ClassA
from .fileB import ClassB

The problem is with package/fileA.py . 问题出在package/fileA.py It's both a part of package and calling the __init__.py file of package as it's imported - creating a circular dependency. 这两个部分package并调用__init__.py的文件package ,因为它的进口-创建一个循环依赖。

Can you change fileA.py to look like this? 您可以将fileA.py更改为以下形式吗?

# package/fileA.py
from .fileB import ClassB

def ClassA:
    def __init__(self):
        self.my_ClassB = ClassB()

First of all, renaming your package to literary "package" really confuses this whole situation, but here's my take on it :D. 首先,将您的程序包重命名为文学“程序包”确实使整个情况感到困惑,但这是我的观点:D。
I don't think you are dealing with circular dependency, python just states that it cannot import classB from package and that is because there is no file named classB in package directory. 我不认为您正在处理循环依赖关系,python只是声明它无法从package导入classB ,这是因为package目录中没有名为classB的文件。 Changing import statement to 将导入语句更改为

from package.fileB import ClassB

works because there is directory package which contains file fileB which contains object ClassB . 之所以起作用,是因为有一个目录package ,其中包含文件fileB ,其中包含对象ClassB
To answer your question whether you can import classes with statement 回答您的问题是否可以使用语句导入类

from package import ClassB

you can't, unless your package is file and classB is object inside this file. 您不能,除非您的package是文件,而classB是此文件中的对象。 However i don't see how this different import statement would be a dealbraker 但是我不明白这个不同的导入声明将如何成为交易经纪人
Side Note : Your objects ClassB and ClassA are not classes, they are functions. 注意 :您的对象ClassBClassA不是类,而是函数。 Python uses keyword class to create classes and def to define functions. Python使用关键字class创建类,并使用def定义函数。
Side note 2 : Are you sure your __init__.py file needs to hold any code at all? 旁注2 :您确定__init__.py文件根本不需要保留任何代码吗?
Personal Note : I know that keeping 1 File / 1 Class structure is matter of personal preferences, it is not required in python and I myself find it much more comfortable to group multiple related classes and functions into one file 个人说明 :我知道保留1 File / 1 Class结构是个人喜好问题,在python中不是必需的,我自己发现将多个相关的类和函数组合到一个文件中会更舒适

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

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