Python导入错误:'module'对象没有'x'属性

时间:2022-04-12 07:58:56

I am trying to do a python script that it is divided in multiple files, so I can maintain it more easily instead of making a very-long single file script.

我正在尝试做一个python脚本,它被分割成多个文件,因此我可以更容易地维护它,而不是创建一个非常长的单一文件脚本。

Here is the directory structure:

以下是目录结构:

wmlxgettext.py
<pywmlx>
  |- __init__.py
  |- (some other .py files)
  |- <state>
       |- __init__.py
       |- state.py
       |- machine.py
       |- lua_idle.py

if I reach the main directory of my project (where the wmlxgettext.py script is stored) and if I try to "import pywmlx" I have an import error (Attribute Error: 'module' object has no attribute 'state')

如果我到达项目的主目录(wmlxgettext)。如果我尝试“导入pywmlx”,就会有一个导入错误(属性错误:'module'对象没有属性'state')

Here is the complete error message:

以下是完整的错误信息:

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/home/user/programmi/my/python/wmlxgettext/true/pywmlx/__init__.py", line 9, in <module>
    import pywmlx.state as statemachine
  File "/home/user/programmi/my/python/wmlxgettext/true/pywmlx/state/__init__.py", line 1, in <module>
    from pywmlx.state.machine import setup
  File "/home/user/programmi/my/python/wmlxgettext/true/pywmlx/state/machine.py", line 2, in <module>
    from pywmlx.state.lua_idle import setup_luastates
  File "/home/user/programmi/my/python/wmlxgettext/true/pywmlx/state/lua_idle.py", line 3, in <module>
    import pywmlx.state.machine as statemachine
AttributeError: 'module' object has no attribute 'state'

Since I am in the "project main directory" pywmlx should be on PYTHONPATH (infact I have no troubles when I tried to import pywmlx/something.py)

因为我在“项目主目录”pywmlx中,所以应该在PYTHONPATH中(事实上,当我尝试导入pywmlx/something.py时,我没有遇到任何麻烦)

I'm not able to figure where is my error and how to solve this problem.

我不知道我的错误在哪里,如何解决这个问题。

Here is the pywmlx/__init__.py source:

这是pywmlx / __init__。py来源:

# all following imports works well:
from pywmlx.wmlerr import ansi_setEnabled
from pywmlx.wmlerr import wmlerr
from pywmlx.wmlerr import wmlwarn
from pywmlx.postring import PoCommentedString
from pywmlx.postring import WmlNodeSentence
from pywmlx.postring import WmlNode 

# this is the import that does not work:
import pywmlx.state as statemachine

Here is the pywmlx/state/__init__.py source:

这是pywmlx /状态/ __init__。py来源:

from pywmlx.state.machine import setup
from pywmlx.state.machine import run

But I think that the real problem is somewhat hidden in the "imports" used by one (or all) python modules stored in pywmlx/state directory.

但是我认为真正的问题隐藏在pywmlx/state目录中存储的一个(或所有)python模块使用的“导入”中。

Here is the pywmlx/state/machine.py source:

这是pywmlx /国家/机器。py来源:

# State is a "virtual" class
from pywmlx.state.state import State
from pywmlx.state.lua_idle import setup_luastates
import pywmlx.nodemanip as nodemanip

def addstate(self, name, value):
    # code is not important for this question
    pass

def setup():
    setup_luastates()

def run(self, *, filebuf, fileref, fileno, startstate, waitwml=True):
    # to do
    pass

Finally here is the pywmlx/state/lua_idle.py source:

最后是pywmlx/state/lua_idle。py来源:

import re
import pywmlx.state.machine as statemachine
# State is a "virtual" class
from pywmlx.state.state import State

# every state is a subclass of State
# all proprieties were defined originally on the base State class:
    # self.regex and self.iffail were "None"
    # the body of "run" function was only "pass"
class LuaIdleState (State):
    def __init__(self):
        self.regex = re.compile(r'--.*?\s*#textdomain\s+(\S+)', re.I)
        self.iffail = 'lua_checkpo'

    def run(xline, match):
        statemachine._currentdomain = match.group(1)
        xline = None
        return (xline, 'lua_idle')


def setup_luastates():
    statemachine.addstate('lua_idle', LuaIdleState)

Sorry if I posted so much code and so many files... but I fear that the files, in directory, hides more than a single import problem, so I published them all, hoping that I could explain the problem avoiding confusion.

抱歉,如果我发布了这么多的代码和文件……但是我担心目录中的文件隐藏了不止一个导入问题,所以我将它们全部发布,希望能够解释这个问题,避免混淆。

I think that I miss something about how import works in python, so I hope this question can be useful also to other programmers, becouse I think I am not the only one who found the official documentation very difficult to understand when explaining import.

我想我漏掉了一些关于import如何在python中工作的内容,所以我希望这个问题对其他程序员也有用,因为我认为我不是唯一一个在解释import时发现官方文档非常难以理解的人。


Searches Done:

搜索完成:

Not Useful: I am already explicitly using import x.y.z all times I need to import something

无用:我已经显式地使用了import x.y。z总是需要导入一些东西

Not Useful: Even if the question asks about import errors, it seems not useful for the same reason as (1)

没有用处:即使问题问的是导入错误,它似乎也没有用处,原因与(1)相同。

Not Useful: As far as I know, pywmlx should be located into PYTHONPATH since "current working directory" on my tests is the directory that contains the main python script and pywmlx directory. Correct me if I am wrong

不实用:据我所知,pywmlx应该位于PYTHONPATH中,因为我的测试中的“当前工作目录”是包含主python脚本和pywmlx目录的目录。如果我错了请纠正我

2 个解决方案

#1


9  

Python does several things when importing packages:

Python在导入包时做以下几件事:

  • Create an object in sys.modules for the package, with the name as key: 'pywmlx', 'pywmlx.state', 'pywmlx.state.machine', etc.
  • 在sys中创建一个对象。包的模块,名称为key: 'pywmlx', 'pywmlx。”、“pywmlx.state状态。机”,等等。
  • Run the bytecode loaded for that module; this may create more modules.
  • 运行为该模块加载的字节码;这可能会创建更多的模块。
  • Once a module is fully loaded and it is located inside another package, set the module as an attribute of the parent module object. Thus the sys.modules['pywmlx.state'] module is set as the state attribute on the sys.modules['pywmlx'] module object.
  • 一旦模块被完全加载,并且它位于另一个包中,将模块设置为父模块对象的属性。因此,sys.modules[' pywmlx。模块设置为系统的状态属性。模块(“pywmlx”)模块对象。

That last step hasn't taken place yet in your example, but the following line only works when it has been set:

在您的示例中,最后一个步骤还没有发生,但是下面一行只有在设置时才会起作用:

import pywmlx.state.machine as statemachine

because this looks up both state and machine as attributes first. Use this syntax instead:

因为它首先将状态和机器作为属性查找。使用这种语法:

from pywmlx.state import machine as statemachine

Alternatively, just use

另外,用

import pywmlx.state.machine

and replace statemachine. everywhere else with pywmlx.state.machine.. This works because all that is added to your namespace is a reference to the sys.modules['pywmlx'] module object and the attribute references won't need to be resolved until you use that reference in the functions and methods.

和替换statemachine。其他地方与pywmlx.state.machine . .这之所以有效,是因为添加到名称空间的所有内容都是对sys的引用。模块['pywmlx']模块对象和属性引用不需要解析,除非您在函数和方法中使用该引用。

#2


2  

You are having a circular import in your framework. Circular imports do not work well with aliases. When importing a module with an alias and then, during the circular import, importing it again without an alias, python complains. The solution is to not use aliases (the "import module as" syntax) but always use the full "import module" statement.

在框架中有一个循环导入。循环导入不能很好地处理别名。当导入一个具有别名的模块,然后在循环导入期间,在没有别名的情况下再次导入模块时,python会抱怨。解决方案是不使用别名(“导入模块作为”语法),而是始终使用完整的“导入模块”语句。

#1


9  

Python does several things when importing packages:

Python在导入包时做以下几件事:

  • Create an object in sys.modules for the package, with the name as key: 'pywmlx', 'pywmlx.state', 'pywmlx.state.machine', etc.
  • 在sys中创建一个对象。包的模块,名称为key: 'pywmlx', 'pywmlx。”、“pywmlx.state状态。机”,等等。
  • Run the bytecode loaded for that module; this may create more modules.
  • 运行为该模块加载的字节码;这可能会创建更多的模块。
  • Once a module is fully loaded and it is located inside another package, set the module as an attribute of the parent module object. Thus the sys.modules['pywmlx.state'] module is set as the state attribute on the sys.modules['pywmlx'] module object.
  • 一旦模块被完全加载,并且它位于另一个包中,将模块设置为父模块对象的属性。因此,sys.modules[' pywmlx。模块设置为系统的状态属性。模块(“pywmlx”)模块对象。

That last step hasn't taken place yet in your example, but the following line only works when it has been set:

在您的示例中,最后一个步骤还没有发生,但是下面一行只有在设置时才会起作用:

import pywmlx.state.machine as statemachine

because this looks up both state and machine as attributes first. Use this syntax instead:

因为它首先将状态和机器作为属性查找。使用这种语法:

from pywmlx.state import machine as statemachine

Alternatively, just use

另外,用

import pywmlx.state.machine

and replace statemachine. everywhere else with pywmlx.state.machine.. This works because all that is added to your namespace is a reference to the sys.modules['pywmlx'] module object and the attribute references won't need to be resolved until you use that reference in the functions and methods.

和替换statemachine。其他地方与pywmlx.state.machine . .这之所以有效,是因为添加到名称空间的所有内容都是对sys的引用。模块['pywmlx']模块对象和属性引用不需要解析,除非您在函数和方法中使用该引用。

#2


2  

You are having a circular import in your framework. Circular imports do not work well with aliases. When importing a module with an alias and then, during the circular import, importing it again without an alias, python complains. The solution is to not use aliases (the "import module as" syntax) but always use the full "import module" statement.

在框架中有一个循环导入。循环导入不能很好地处理别名。当导入一个具有别名的模块,然后在循环导入期间,在没有别名的情况下再次导入模块时,python会抱怨。解决方案是不使用别名(“导入模块作为”语法),而是始终使用完整的“导入模块”语句。