简体   繁体   English

如何使用pip处理python应用程序的C扩展?

[英]How to handle C extensions for python apps with pip?

For python applications that install with pip , how can you handle their C extension requirements automatically? 对于使用pip安装的python应用程序,如何自动处理其C扩展要求?

For example, the mysqlclient module requires development libs of MySQL installed on the system. 例如, mysqlclient模块需要在系统上安装MySQL的开发库。 When you initially install an application requiring that module it'll fail if the MySQL development libraries are not on the system. 当您最初安装需要该模块的应用程序时,如果MySQL开发库不在系统上,它将会失败。 So the question is how do I solve this? 所以问题是我该如何解决这个问题?

  1. Is there a way to solve this with setup.py already that I do not know about? 有没有办法用setup.py来解决这个问题我已经不知道了?
  2. If not am I supposed to use a pure python module implementation? 如果不是,我应该使用纯python模块实现?

Note; 注意; I'm not looking for answers like " just use py2exe ". 不是在寻找像“ 只使用py2exe ”这样的答案。

No . There is no way of including totally separate C library as a part of your build process unless you are writing an extension . 除非您正在编写扩展,否则无法将完全独立的C库作为构建过程的一部分。 Even in that case, you'll need to specify all .c files in ext_modules so that they all can be compiled as a part of your build process, which I know is not what you want. 即使在这种情况下,您还需要在ext_modules中指定所有.c文件,以便它们都可以编译为构建过程的一部分,我知道这不是您想要的。

The only thing you can do is to simply stop the build process and give user a reasonable error if mysql-devel (or libmysqlclient-dev ) has not yet been installed. 您唯一能做的就是简单地停止构建过程,如果尚未安装mysql-devel (或libmysqlclient-dev ),则会给用户一个合理的错误。

One way to know if mysql-dev is installed is writing a simple C function that imports mysql.h and check if it is compiled successfully. 知道是否安装了mysql-dev的一种方法是编写一个简单的C函数,它导入mysql.h并检查它是否已成功编译。

Note: mysql.h and my_global.h is part of libmysqlclient-dev package. 注意: mysql.h和my_global.h是libmysqlclient-dev包的一部分。


test/test_mysqlclient.c 测试/ test_mysqlclient.c

// Taken from: http://zetcode.com/db/mysqlc

#include <my_global.h>
#include <mysql.h>

int main(int argc, char **argv)
{
  printf("MySQL client version: %s\n", mysql_get_client_info());
  exit(0);
}

Secondly, let's update our setup.py file so that it will be included as a part of the build process. 其次,让我们更新我们的setup.py文件,以便它作为构建过程的一部分包含在内。

setup.py setup.py

#!/usr/bin/env python

import os
import subprocess

from setuptools import setup, Extension

def mysql_test_extension():
    process = subprocess.Popen(['which', 'mysql_config'],
                               stdout=subprocess.PIPE,
                               stderr=subprocess.PIPE,
                               close_fds=True)

    result, error = process.communicate()
    if process.returncode > 0:
        raise RuntimeError(error)

    config_command = result.strip()

    cflags = subprocess.check_output([config_command, '--cflags'], close_fds=True).strip()

    include_dirs = []
    extra_compile_args = []
    for arg in cflags.split(' '):
        if not arg.strip():
            continue
        elif arg.startswith('-I'):
            include_dirs.append(arg[2:])
        elif arg.startswith('-'):
            extra_compile_args.append(arg)
        else:
            extra_compile_args[-1] = extra_compile_args[-1] + ' ' + arg

    libs = subprocess.check_output([config_command, '--libs'], close_fds=True).strip()

    libraries = []
    linkers = []
    for arg in libs.split(' '):
        if not arg.strip():
            continue
        elif arg.startswith('-L'):
            libraries.append(arg[2:])
        elif arg.startswith('-'):
            linkers.append(arg)
        else:
            linkers[-1] = extra_compile_args[-1] + ' ' + arg

    return Extension('test_mysqlclient', ['test/test_mysqlclient.c'],
                     include_dirs=include_dirs,
                     library_dirs=libraries,
                     extra_link_args=linkers,
                     extra_compile_args=extra_compile_args)



setup(name='python-project',
      version='1.0',
      description='Python Project',
      classifiers=[
          'Development Status :: 5 - Production/Stable',
          'Environment :: Console',
          'Intended Audience :: Developers',
          'License :: OSI Approved :: MIT License',
          'Operating System :: OS Independent',
          'Programming Language :: Python :: 2.7',
          'Natural Language :: English',
      ],
      keywords='mysql python project',
      author='Ozgur Vatansever',
      url='http://github.com/ozgur/python-project/',
      license='MIT',
      packages=['some_project'],
      ext_modules = [mysql_test_extension()]
)

You can start building your package along with the test_mysqlclient file: 您可以开始构建包以及test_mysqlclient文件:

$ python setup.py build

If mysql-devel is not installed on your system, you'll get an build error similar to this: 如果您的系统上没有安装mysql-devel ,您将收到类似于此的构建错误:

test/test_mysqlclient.c:3:10: fatal error: 'my_global.h' file not found
#include <my_global.h>
     ^
1 error generated.

So the question is how do I solve this? 所以问题是我该如何解决这个问题?

You have not solve this problem anyhow. 无论如何你还没有解决这个问题。 There is no any method to describe external dependencies outside of python ecosystem in setup.py. 在setup.py中没有任何方法可以描述python生态系统之外的外部依赖关系。 Just provide it in a README. 只需在自述文件中提供即可。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM