在Python中为每个文件实现一个函数的正确方法

时间:2017-01-18 19:28:54

标签: python

我正在开发一个模块来帮助我处理文件,这就是结构:

Archive/
| archive/
  - __init__.py
  - move.py
  - rename.py
  - mime_type.py
| setup.py

我正在设计一个文件 - 一个功能。对我来说,它更好,我觉得这种风格更舒服,因为我有一个Node.js和C / C ++背景。

所以,我怀疑如何实现__init__.py能够使用以下方法调用函数:

from archive import move
from archive import rename
from archive import mime_type

而不是:

from archive import move.move
from archive import rename.rename
from archive import mime_type.mime_type

我这样做:

__init__.py

from move import move
from rename import rename
from mime_type import mime_type

是否有更简单的方法来自动实现此行为?无需每次创建文件时都更改__init__.py

感谢。

4 个答案:

答案 0 :(得分:1)

您可以使用importlib导入模块,然后使用globals()getattr动态分配函数名称:

from importlib import import_module
for f in ["move","rename","mime_type"]:
    import_module("."+f,"archive") #import archive.f
    globals()[f]=getattr(globals[f],f) #assign the function f.f to variable f 

根据tdelaney的建议,您甚至可以使用glob动态获取所有模块名称:

from os.path import splitext,join,basename,dirname
from glob import glob  
#get all *.py filenames in __file__'s folder that are not __file__.
files=[splitext(f)[0] for f in glob(join(dirname(__file__), '*.py')) 
       if f != basename(__file__)] 
for f in files:
    ...

答案 1 :(得分:1)

使用'作为':

from archive import move.move as move
from archive import rename.rename as rename
from archive import mime_type.mime_type as mime_type

答案 2 :(得分:0)

Saulpila's answer为基础,我得出以下结论:

import os.path
from glob import glob

# Get all *.py filenames in __init__'s folder
full_paths = glob(os.path.join(os.path.dirname(__file__), '*.py'))

# Remove path prefix and remove __init__.py from the list
file_names = [os.path.split(f)[1] for f in full_paths if f != __file__]

# Remove extension
files = [os.path.splitext(f)[0] for f in file_names]

for f in files:
    # from archive import f (__name__ is 'archive')
    __import__(__name__+'.'+f, globals=globals())

    # assign the function f.main to variable f
    globals()[f]=getattr(globals()[f], 'main')

答案 3 :(得分:0)

我的方法是使用exec()

__init__.py

import glob
mod_list = [file_name.split('/')[-1].split('.')[0] for file_name in glob.glob(__path__[0]+'/[!_]*.py')]
sub_pack_list = [folder_name.split('/')[-2] for folder_name in glob.glob(__path__[0]+'/[!_]*/')]

# import functions
for mod in mod_list:
    exec('from . import ' + mod)
    exec('from .' + mod + ' import *')

# import subpackages
for pack in sub_pack_list:
    exec('from . import ' + pack)

# clean up
del glob
try:
    del mod
except:
    pass
try:
    del pack
except:
    pass

import archive之后,您将看到archive.move()可用。

作为奖励效果,您可以使用archive.mod_listarchive.sub_pack_list。如果您不喜欢它们,也可以在__init__.py中将其删除。

再走一步

您仍然可以在文件中具有多个功能,比如说move_file()中有两个功能move_folder()move.py。您可以添加最后一行

__all__ = ['move_file', 'move_folder']
move.py

控制archive.***范围内应该可用的功能