从外部脚本从 setup.py 导入变量
Import a variable from setup.py from an external script
我有一个这样的 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单线会很棒。
在文档中: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"])
除了从任意路径导入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 import of ext_modules
:
import sys
class fake_ext_module():
executor_module = 'spam'
sys.modules['ext_modules'] = fake_ext_module
我有一个这样的 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单线会很棒。
在文档中: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"])
除了从任意路径导入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 import of ext_modules
:
import sys
class fake_ext_module():
executor_module = 'spam'
sys.modules['ext_modules'] = fake_ext_module