Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/python-3.x/15.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何在不导入包含函数的文件的情况下将函数导入Python包?_Python_Python 3.x_Import_Package_Python Import - Fatal编程技术网

如何在不导入包含函数的文件的情况下将函数导入Python包?

如何在不导入包含函数的文件的情况下将函数导入Python包?,python,python-3.x,import,package,python-import,Python,Python 3.x,Import,Package,Python Import,我在Mac OSX上使用Python 3.4.2,我有一个简单的版本控制Python项目,其目录/文件结构如下: vcs_projectname/ foo/ __init__.py simplefunc.py docs/ other_related_stuff/ from .simplefunc import helloworld __all__ = ['helloworld'] # Not sure whether I really n

我在Mac OSX上使用Python 3.4.2,我有一个简单的版本控制Python项目,其目录/文件结构如下:

vcs_projectname/
    foo/
        __init__.py
        simplefunc.py
    docs/
    other_related_stuff/
from .simplefunc import helloworld
__all__ = ['helloworld'] # Not sure whether I really need this line...?
def helloworld():
    print('Hello world!')
\uuuu init\uuuu.py
文件如下所示:

vcs_projectname/
    foo/
        __init__.py
        simplefunc.py
    docs/
    other_related_stuff/
from .simplefunc import helloworld
__all__ = ['helloworld'] # Not sure whether I really need this line...?
def helloworld():
    print('Hello world!')
simplefunc.py
文件如下所示:

vcs_projectname/
    foo/
        __init__.py
        simplefunc.py
    docs/
    other_related_stuff/
from .simplefunc import helloworld
__all__ = ['helloworld'] # Not sure whether I really need this line...?
def helloworld():
    print('Hello world!')
我通过更改到项目层次结构之外的目录来测试代码,将my
PYTHONPATH
环境变量(在bash中)设置为指向
vcs\u projectname
基本目录,并启动:

在ipython中,我导入包foo,然后查看其目录结构,结果如下:

In [1]: import foo

In [2]: dir(foo)
Out[2]: 
['__all__',
 '__builtins__',
 '__cached__',
 '__doc__',
 '__file__',
 '__loader__',
 '__name__',
 '__package__',
 '__path__',
 '__spec__',
 'helloworld',
 'simplefunc']

我的问题是:如何去掉包目录结构中对
simplefunc
文件模块的引用?这样做是可取的,因为在最好的情况下,它只是无用的杂乱(我们不需要它,因为我们真正想要的东西,
helloworld()
函数已经由
\uu init\uuuuuuuuuuuy.py
文件在包级别提供了),在最坏的情况下,它本质上是对一个不相关的实现细节(项目的底层文件结构)的引用,以后可能会更改,因此我不希望我的用户在未来的版本中期待和依赖它。

您试图做的事情是不可能优雅的。正如@Lukas所提到的,有一些黑客可以做到这一点

相反,我一直在遵循的是,创建一个名为
\u private
的子包,并将所有这些模块放在其中。这样,当用户导入包时,所有公开的API都可用,而私有API则隐藏在
\u private

示例:

foo/
    __init__.py
    _private/
        __init__.py
        test1.py
        test2.py
from _private import bar, baz
from test1 import bar
from test2 import baz
def bar():
    print "bar"
def baz():
    print "baz"
>>> import foo
>>> dir(foo)
['__builtins__', '__doc__', '__file__', '__name__', '__package__', '__path__', '_private', 'bar', 'baz']
foo/\uuuu init\uuuu.py

foo/
    __init__.py
    _private/
        __init__.py
        test1.py
        test2.py
from _private import bar, baz
from test1 import bar
from test2 import baz
def bar():
    print "bar"
def baz():
    print "baz"
>>> import foo
>>> dir(foo)
['__builtins__', '__doc__', '__file__', '__name__', '__package__', '__path__', '_private', 'bar', 'baz']
foo/\u private/\uu init\uuuuuuuupy

foo/
    __init__.py
    _private/
        __init__.py
        test1.py
        test2.py
from _private import bar, baz
from test1 import bar
from test2 import baz
def bar():
    print "bar"
def baz():
    print "baz"
>>> import foo
>>> dir(foo)
['__builtins__', '__doc__', '__file__', '__name__', '__package__', '__path__', '_private', 'bar', 'baz']
foo/\u private/test1.py

foo/
    __init__.py
    _private/
        __init__.py
        test1.py
        test2.py
from _private import bar, baz
from test1 import bar
from test2 import baz
def bar():
    print "bar"
def baz():
    print "baz"
>>> import foo
>>> dir(foo)
['__builtins__', '__doc__', '__file__', '__name__', '__package__', '__path__', '_private', 'bar', 'baz']
foo/\u private/test2.py

foo/
    __init__.py
    _private/
        __init__.py
        test1.py
        test2.py
from _private import bar, baz
from test1 import bar
from test2 import baz
def bar():
    print "bar"
def baz():
    print "baz"
>>> import foo
>>> dir(foo)
['__builtins__', '__doc__', '__file__', '__name__', '__package__', '__path__', '_private', 'bar', 'baz']
导入
foo

foo/
    __init__.py
    _private/
        __init__.py
        test1.py
        test2.py
from _private import bar, baz
from test1 import bar
from test2 import baz
def bar():
    print "bar"
def baz():
    print "baz"
>>> import foo
>>> dir(foo)
['__builtins__', '__doc__', '__file__', '__name__', '__package__', '__path__', '_private', 'bar', 'baz']
如何在包目录结构中去掉对simplefunc文件模块的引用

您可以通过将
del simplefunc
添加到
foo/\uuuu init\uuuuuu.py
中来实现所述目标,如下所示:

from  .simplefunc import helloworld
del simplefunc
__all__ = ['helloworld'] # Not sure whether I really need this line...?

您可以
del
ete引用。但我不会。好的,我只是在导入实际完成后在[3]:del(foo.simplefunc)中的ipython命令行中尝试了这一点,从技术上讲它确实有效,但肯定有比这更优雅的解决方案吗?有没有其他方法可以让我构造
\uuu init\uuuuuuy.py
文件本身,以获得相同的结果,这不仅仅是一个丑陋的混乱或解决方法?问题是,您试图实现的最终目标是一个丑陋的混乱(在我看来)。您将对用户隐藏源代码结构,这可能会使调试变得比需要的更困难,并且非常令人沮丧。使用
\u下划线
前缀和文档来明确您的代码的哪些部分是包的公共API的一部分,哪些部分是不正确的。因此,明确地说,您建议的解决方案本质上是,如果我想这样做,然后,我应该考虑将<代码> SimeFunc.Py < /code >文件改写为简单SimeFun.Py < /code >,以使底层源代码文件结构暴露,但仍然向用户表明它不打算成为公共API的一部分。我正确地描述了你的位置吗?是的,这就是我的意思,这将是清楚地表明你认为这个模块(名称/位置)是内部细节的明显方式。但这通常甚至不是必需的:如果您确实在某个点上更改了代码布局,并移动模块、合并模块等,则始终可以添加内部向后兼容性导入,以确保直接使用“内部”模块的用户的代码仍然有效。见