包__init__.py中导入的模块不可通过点访问

时间:2018-08-10 19:53:31

标签: python python-3.x python-import

这可能是python的理想行为,但我仍然感到困惑-

我具有以下文件结构:

public class SegoeUiEditText extends AppCompatEditText {
private final Context context;


@Override
public boolean isSuggestionsEnabled() {
    return false;
}
public SegoeUiEditText(Context context) {
    super(context);
    this.context = context;
    init();
}

public SegoeUiEditText(Context context, AttributeSet attrs) {
    super(context, attrs);
    this.context = context;
    init();
}

public SegoeUiEditText(Context context, AttributeSet attrs, int defStyle) {
    super(context, attrs, defStyle);
    this.context = context;
    init();
}


private void setFonts(Context context) {
    this.setTypeface(Typeface.createFromAsset(context.getAssets(), "Fonts/Helvetica-Normal.ttf"));
}

private void init() {

        setTextIsSelectable(false);
        this.setCustomSelectionActionModeCallback(new ActionModeCallbackInterceptor());
        this.setLongClickable(false);

}
@Override
public int getSelectionStart() {

    for (StackTraceElement element : Thread.currentThread().getStackTrace()) {
        if (element.getMethodName().equals("canPaste")) {
            return -1;
        }
    }
    return super.getSelectionStart();
}
/**
 * Prevents the action bar (top horizontal bar with cut, copy, paste, etc.) from appearing
 * by intercepting the callback that would cause it to be created, and returning false.
 */
private class ActionModeCallbackInterceptor implements ActionMode.Callback, android.view.ActionMode.Callback {
    private final String TAG = SegoeUiEditText.class.getSimpleName();

    public boolean onCreateActionMode(ActionMode mode, Menu menu) { return false; }
    public boolean onPrepareActionMode(ActionMode mode, Menu menu) { return false; }
    public boolean onActionItemClicked(ActionMode mode, MenuItem item) { return false; }
    public void onDestroyActionMode(ActionMode mode) {}

    @Override
    public boolean onCreateActionMode(android.view.ActionMode mode, Menu menu) {
        return false;
    }

    @Override
    public boolean onPrepareActionMode(android.view.ActionMode mode, Menu menu) {
        menu.clear();
        return false;
    }

    @Override
    public boolean onActionItemClicked(android.view.ActionMode mode, MenuItem item) {
        return false;
    }

    @Override
    public void onDestroyActionMode(android.view.ActionMode mode) {

    }
}

其中repo/ foo/ __init__.py foo/ bar.py 如下:

__init__.py

当我从from .foo import bar 中输入python解释器时,我可以像这样导入repo/

bar

太好了!但是,以下方法不起作用:

>>> from foo import bar
>>> bar
<module 'foo.foo.bar' from '.../repo/foo/foo/bar.py'>

也许我对python的import语句的工作方式不了解,但是我非常希望能够如上所示进行导入。如果这是期望的行为,那么有人知道解决方法吗?也许我可以在>>> import foo.bar as foobar Traceback (most recent call last): File "<stdin>", line 1, in <module> ModuleNotFoundError: No module named 'foo.bar' 中进行更改?

出于对命名注意事项的考虑,我还使用以下文件结构对此进行了测试:

__init__.py

...我得到相同的结果

我已经在linux和macOS上的python 3.6.2和3.6.6中对此进行了测试。我还在python 2.7.13中看到了相同的行为(当然,我在较低的repo/ foo/ __init__.py baz/ bar.py 目录中添加了__init__.py

如果我无法进行这种类型的导入工作,foo/将不得不进行一些重构。帮我防止这种情况!

1 个答案:

答案 0 :(得分:2)

要导入的模块的实际名称为foo.foo.bar。您在from .foo import bar中的__init__.py不会改变。

from foo import bar将为您提供bar模块对象的foo属性,而实际上正是您想要的模块,这要感谢__init__.py中的这一行。不过,import foo.bar需要一个实际的foo.bar模块。如果在sys.modules中找不到该名称的条目,则将引发错误。不要试图用sys.modules来解决这个问题。导致really confusing double-import bugs