【问题标题】:Import a variable from setup.py from an external script从外部脚本从 setup.py 导入变量
【发布时间】:2018-05-07 21:05:21
【问题描述】:

我有一个这样的 setup.py 文件(不在 pwd 中,不在 Python 路径中,在某处是随机文件):

import ext_modules

config = {
    'name': 'mesos.executor',
    'version': '1.4.1',
    'description': 'Mesos native executor driver implementation',
    'author': 'Apache Mesos',
    'author_email': 'dev@mesos.apache.org',
    'url': 'http://pypi.python.org/pypi/mesos.executor',
    'namespace_packages': [ 'mesos' ],
    'packages': [ 'mesos', 'mesos.executor' ],
    'package_dir': { '': 'src' },
    'install_requires': [ 'mesos.interface == 1.4.1' ],
    'license': 'Apache 2.0',
    'keywords': 'mesos',
    'classifiers': [ ],
    'ext_modules': [ ext_modules.executor_module ]
}

from setuptools import setup
setup(**config)

我想从外部 (Python) 脚本导入 config["install_requires"]。我正在寻找最简约的方式来执行此操作,因为它旨在从甚至可能不是 Python 的其他脚本运行。

单线 Python 会很棒。

【问题讨论】:

  • 这不是你需要的吗:from setup import config; config['install_requires'] ?

标签: python python-import


【解决方案1】:

除了从任意路径导入python模块外,还需要避免执行setup(),一种方法是通过AST过滤:

import ast, _ast

def filter_setup_st(node):
    if isinstance(node, _ast.Expr) and isinstance(node.value, _ast.Call):
        if node.value.func.id == 'setup':
            return False
    return True

with open('/path/to/example_setup.py') as f:
    c = f.read()   
tree = ast.parse(c)
tree.body = [n for n in tree.body if filter_setup_st(n)]

ns = {}
exec(compile(tree, '__string__', 'exec'), {}, ns)

assert ns['config']['install_requires'] == ['mesos.interface == 1.4.1']

另一种方法有点棘手,暂时取消setuptools.setup

import setuptools
ori_setup = setuptools.setup
setuptools.setup = lambda *a, **k: 0

ns = {}
exec(compile(c, '__string__', 'exec'), {}, ns)
assert ns['config']['install_requires'] == ['mesos.interface == 1.4.1']

setuptools.setup = ori_setup

更新:

如果您还想要bypass importext_modules

import sys

class fake_ext_module():

    executor_module = 'spam'

sys.modules['ext_modules'] = fake_ext_module

【讨论】:

  • 真的很喜欢第二种方法,实际上有点工作。但是,其中一个 setup.py 尝试导入一个失败的外部模块,因为我没有从预期的文件夹加载。你认为我也可以“取消”导入吗?
【解决方案2】:

在文档中:https://docs.python.org/3/library/importlib.html#importing-a-source-file-directly

在你的情况下:

import importlib
setup_file = "path/to/setup.py"
spec = importlib.util.spec_from_file_location("setup", setup_file)
setup = importlib.util.module_from_spec(spec)
spec.loader.exec_module(setup)
# And now access it
print(setup.config["install_requires"])

【讨论】:

  • 我很确定在导入文件时调用 setup() 方法会有问题
  • 我明白,但解决方法是封装命令:def do_setup(): from setuptools import setup setup(**config) 然后if __name__ == "__main__": do_setup()
猜你喜欢
  • 2021-02-25
  • 1970-01-01
  • 1970-01-01
  • 2020-12-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-11-06
  • 1970-01-01
相关资源
最近更新 更多