【问题标题】:Load source file without a module加载没有模块的源文件
【发布时间】:2016-05-18 14:45:43
【问题描述】:

我想向我的程序传递一个文件并从中获取一个函数。

例如,我有一个文件foo.py,直到运行时才知道其位置(它将通过命令行或类似的方式传递给代码),它可以位于我系统上的任何位置,看起来像这个:

def bar():
    return "foobar"

如何让我的代码运行函数bar

如果在运行时之前知道该位置,我可以这样做:

import sys
sys.path.append("path_to_foo")
import foo

foo.bar()

我可以在foo.py 所在的文件夹中创建一个init.py 文件并使用importlibimp,但它看起来很乱。我不能使用__import__,因为我得到ImportError: Import by filename is not supported.

【问题讨论】:

  • “我可以 [...] 使用 importlib [...] 但它看起来很乱。”当你遇到混乱的问题时,你必须求助于混乱的解决方案。为什么importlib 不够用?
  • 另外,您根本不需要__init__.py 文件。在 Py3 中,更强大的importlib 函数是导入任意文件的正确方法。在早期的 Python 中,您只需将包含 foo.py 的文件夹添加到 sys.path,然后运行 ​​import foo,根本不需要使用特殊的导入功能。
  • foo.py 是否与您的文件在同一目录中?
  • 我使用的是 Python 2.7。我不能使用import foo,因为直到运行时我才知道文件名。
  • 我不想创建一个init.py 文件并将其放在一边,我可以事后清理它。我不知道如何才能确保摆脱它,但这是另一个话题。我必须创建一个空文件来做某事,这似乎是不正当的。

标签: python


【解决方案1】:

您可以使用exec 打开文件并执行它。

f = open('foo.py')
source = f.read()
exec(source)
print bar()

您甚至可以使用re 查找特定功能

【讨论】:

  • 我最终使用了这样的东西。我实际上做了sys.path.append("path_to_foo"); file_name = foo.py; exec(import file_name as foo); foo.bar()
  • @R.Mckemey 你说who's location is not known until run time, can be anywhere on my system...。您将如何找到该文件?
  • 对不起,我不清楚,整个文件路径将传递给程序。我将运行它类似于python program.py path_to_foo/foo.py
  • 需要注意:我尝试将它放在一个函数中,您需要让您的函数返回您感兴趣的任何函数或变量并分配函数调用的结果,否则,函数exec(source) 创建的变量只会存在于函数范围内。
【解决方案2】:

您可以编写一个虚拟函数并在需要的任何地方调用它,以绕过检查:

def bar():
    pass

在运行时用您实际打算使用的函数覆盖该函数,并自动在任何地方使用它。

注意:这比使用importlib 更麻烦。

【讨论】:

  • 我将如何“覆盖函数”?
  • @R.Mckemey 在您确定可以使用的函数代码的位置时动态地使用evalexec 来加载/运行您的函数代码。
【解决方案3】:

如果foo.py和你的主文件在同一个目录下,你可以使用

from . import foo

(Python 3)。这是有效的,因为. 是您的文件目录,Python 会为您导入同一目录中的文件。然后你可以使用

foo.bar()

如果不是,则需要找到它,然后执行:

import os
from os.path import join

lookfor = "foo.py"
for root, dirs, files in os.walk('C:\\'): # or '/' for Linux / OSX
    if lookfor in files:
        execfile(join(root, lookfor)) # Python 2, or
        with open(join(root, lookfor)) as file:
            exec(''.join(file.readlines()))
        break
foo.bar()

致谢:Martin Stone。我不只是复制代码,我理解代码,并且可以自己制作。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-07-26
    • 1970-01-01
    • 1970-01-01
    • 2017-01-02
    • 2017-02-07
    • 1970-01-01
    • 2020-08-25
    • 1970-01-01
    相关资源
    最近更新 更多