从外部脚本从setup.py导入变量

2022-03-31 00:00:00 python python-import

问题描述

我有一个这样的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)脚本导入配置["Install_Requires"]。我正在寻找最简约的方式来完成这项工作,因为它的目的是从其他脚本运行,甚至可能不是Python。

一个Python一行程序就太棒了。


解决方案

除了从任意路径导入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

更新:

如果您还需要ext_modules的bypass import:

import sys

class fake_ext_module():

    executor_module = 'spam'

sys.modules['ext_modules'] = fake_ext_module

相关文章