如何从Python内部检测包是否由conda管理

如何从Python内部检测包是否由conda管理,python,conda,Python,Conda,我想从Python会话中以一般方式检测它是否由conda管理 一些不够笼统的想法不太有用: 1:使用环境变量 如中所述 这在根conda环境中似乎不起作用,因为这些变量并不总是定义的。如果您在使用另一个Python安装时碰巧激活了conda,那么它也有潜在的误报 2:检查可执行路径 在用户以默认路径安装anaconda/miniconda的情况下,这将起作用。否则它可能会失败。也很容易想象假阳性 3.检查版本信息 如回答中所述,在某些情况下,您可以检查Python版本字符串: import sy

我想从Python会话中以一般方式检测它是否由conda管理

一些不够笼统的想法不太有用:

1:使用环境变量 如中所述

这在根conda环境中似乎不起作用,因为这些变量并不总是定义的。如果您在使用另一个Python安装时碰巧激活了conda,那么它也有潜在的误报

2:检查可执行路径 在用户以默认路径安装anaconda/miniconda的情况下,这将起作用。否则它可能会失败。也很容易想象假阳性

3.检查版本信息 如回答中所述,在某些情况下,您可以检查Python版本字符串:

import sys
is_conda = ('Continuum Analytics' in sys.version) or ('Anaconda' in sys.version)
目前,这适用于从默认通道安装的Python,但这相当脆弱,将来可能会中断,特别是随着Continuum公司名称的更改。如果Python是从第三方源(如conda forge)安装的,它也可能失败

4.检查
conda
导入 只要您在根conda环境中,此功能就可以工作,但如果您在另一个默认未安装
conda
包的conda环境中,则通常会失败

5:尝试
conda
查看它是否有效 阿托·阿拉斯的建议:

这在最简单的情况下有效,但在Jupyter中使用多个内核的常见情况下失败,
conda
可执行文件可能连接到当前Python内核,也可能没有连接到当前Python内核


是否有任何完全通用的方法从Python中检测Python安装是否由conda管理?

可能是这样

from subprocess import check_output, CalledProcessError
import sys


def is_conda_managed():
    try:
        out = check_output(['conda', 'env', 'list']).decode('utf-8')
        lines = (line for line in out.splitlines() if line[:1] != '#')
        roots = set(line.split()[-1] for line in lines if line.strip())
    except CalledProcessError:
        roots = set()

    return sys.prefix in roots

使用编译时标志似乎是相当准确的,并且有望保持稳定

def is_conda():
    import sysconfig
    return 'conda-bld' in sysconfig.get_config_var("abs_srcdir")
我不确定特定的键“abs\u srcdir”,但是
sysconfig.get\u config\u values()
有许多项可能有效。在我的系统python中,它是:

>>> sysconfig.get_config_var("abs_srcdir")
'/Library/Caches/com.apple.xbs/Binaries/python/python-97.50.7~5/TempContent/Objects/2.7/python'
In [17]: sysconfig.get_config_var("abs_srcdir")
Out[17]: '/Users/ilan/minonda/conda-bld/python-3.6_1482520641897/work/Python-3.6.0'
我的conda python是:

>>> sysconfig.get_config_var("abs_srcdir")
'/Library/Caches/com.apple.xbs/Binaries/python/python-97.50.7~5/TempContent/Objects/2.7/python'
In [17]: sysconfig.get_config_var("abs_srcdir")
Out[17]: '/Users/ilan/minonda/conda-bld/python-3.6_1482520641897/work/Python-3.6.0'

我希望编译时标志比运行时检查更健壮。在“conda”子目录中安装Python.org可能会混淆诸如“is conda in sys.prefix”之类的运行时内容。但是编译时标志应该是可以的。

当我通读这些想法及其缺点时,我并不完全清楚“管理”是什么意思

import sys, os
is_conda = os.path.exists(os.path.join(sys.prefix, 'conda-meta'))
└─╼ which -a python
/Users/me/anaconda/bin/python
/usr/bin/python
┌─[ ~/myPython]
└─╼ /Users/me/anaconda/bin/python
Python 2.7.13 |Anaconda 2.2.0 (x86_64)| (default, Dec 20 2016, 23:05:08) 
[GCC 4.2.1 Compatible Apple LLVM 6.0 (clang-600.0.57)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
Anaconda is brought to you by Continuum Analytics.
Please check out: http://continuum.io/thanks and https://anaconda.org
>>> quit()
┌─[ ~/myPython]
└─╼ /usr/bin/python
Python 2.7.10 (default, Feb  7 2017, 00:08:15) 
[GCC 4.2.1 Compatible Apple LLVM 8.0.0 (clang-800.0.34)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> quit()
┌─[ ~/myPython]
└─╼ source activate py36
(py36) ┌─[ ~/myPython]
└─╼ which -a python
/Users/me/anaconda/envs/py36/bin/python
/Users/me/anaconda/bin/python
/usr/bin/python
└─╼ python
Python 3.6.2 |Continuum Analytics, Inc.| (default, Jul 20 2017, 13:14:59) 
[GCC 4.2.1 Compatible Apple LLVM 6.0 (clang-600.0.57)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> quit()
(py36) ┌─[ ~/myPython]
└─╼ which -a python
/Users/me/anaconda/envs/py36/bin/python
/Users/me/anaconda/bin/python
/usr/bin/python
这些线路是: Python 2.7.10(默认值 Python 2.7.13 | Anaconda 2.2.0(x86_64) Python 3.6.2 |连续分析公司

或多或少,你想捕捉什么?当然,这些并不总是出现,最好是脆弱的。使用平台检查图像可能是朝着一个有用的方向迈出的一步

In [46]: platform.python_build()
Out[46]: ('default', 'Jul 20 2017 13:14:59')

In [47]: platform.python_compiler()
Out[47]: 'GCC 4.2.1 Compatible Apple LLVM 6.0 (clang-600.0.57)'

In [48]: platform.python_implementation()
Out[48]: 'CPython'
我想,这些都是康达的替代品,所以q似乎比康达更宽


(这是一个答案,只是因为这是我的第一篇SO帖子,我只有一个声誉)

我认为最好的方法是一个变体:在构建过程中,conda调用了
{sys.prefix}/conda meta/history
,因此检查它的存在应该告诉您是否以一种合理稳健的方式使用conda:

import sys, os
is_conda = os.path.exists(os.path.join(sys.prefix, 'conda-meta', 'history'))

这种方法仍然有可能出现误报,但在我看来,除非故意这样做,否则不太可能发生。

您有什么具体的事情要检查吗?也许解决这个问题会更容易…我想从Python内部检查是否应该使用pip或conda来安装新包。您可以检查
path.join(sys.prefix,“bin”,“conda”)
path.join(sys.prefix,“Scripts”,“conda.exe”)
存在。例如,PyInstaller中也需要这样做,以便它可以找到DLL等。这是我在
/tmp/test
中创建环境时得到的结果:
sysconfig.get\u config\u vars('abs\u srcdir')['/tmp/test/./work/Python-3.6.3']
这是一个基于conda的环境吗?好主意!我也用从conda forge安装的python进行了检查,
'conda-bld
也在那里。尽管如此,仍然有点担心角落案例中的失败…@TomAugspurger是的。这是使用默认通道中的最新conda,使用
conda create-p/tmp/test pyt创建的hon
次要建议:使用
os.path.join
将其应用于Windows。它在Windows中应该可以正常工作。我想os.join更向后兼容。好方法!虽然我认为
conda meta
仅在根环境路径中,是吗?如果您将其更改为
conda
并使用
os.path.join
对于windows兼容性,我认为这可能是最好的答案。我认为这样一种方法,即
sys.prefix
看起来像conda环境是最好的选择。如果我使用
os.path.join(sys.prefix,'conda meta')
,它对
dirname(sys.executable)不起作用
。另外,要明确的是:路径连接的问题不是f字符串在Windows中不起作用;问题是Windows在路径中使用
\
,而不是
/
os.path.join
会自动处理这个问题。你介意编辑答案吗?谢谢!我看到t的一个潜在问题他的意思是,如果有人在他们的系统上安装了两个conda副本,你可能会遇到这样的情况:当它应该返回True时,它返回False,因为它在错误的conda envs集合中查找。它拾取的
conda
是安装时要使用的(IMO)不一定:例如,如果您使用的是Jupyter笔记本,那么它获取的conda包就是启动
Jupyter笔记本
时路径中的一个。如果机器上有多个anaconda/miniconda安装,笔记本可以轻松指向与另一个conda安装关联的Python内核,在这种情况下这个解决方案会失败。在帮助学生解决问题时,我见过很多次这种情况
In [46]: platform.python_build()
Out[46]: ('default', 'Jul 20 2017 13:14:59')

In [47]: platform.python_compiler()
Out[47]: 'GCC 4.2.1 Compatible Apple LLVM 6.0 (clang-600.0.57)'

In [48]: platform.python_implementation()
Out[48]: 'CPython'
import sys, os
is_conda = os.path.exists(os.path.join(sys.prefix, 'conda-meta', 'history'))