【问题标题】:Python3 reload project that use python c-api使用 python c-api 的 Python3 重新加载项目
【发布时间】:2020-11-16 17:51:51
【问题描述】:

我有一个项目,我为它构建了一个 C 类 (python c-api),我在 python 项目中对其进行了更多扩展。该项目的目的是为 C 库提供一个测试框架。测试主要针对C库的每个pull request执行。

项目需要从Nexus服务器下载相关构建的C库,编译依赖C库的python类,然后进行测试。

问题:C代码编译后导入/重新加载项目模块。

问题:在我看来,在依赖C库的每个函数中都做import并不是那么优雅,所以我尝试调用reload,但似乎不起作用,或者至少不像我预期的那样。

代码为了说明问题,代码被超级简化了,你可以查看这个线程历史来查看之前的代码。

main.py

from utils.my_custom_py import MyCustomExtended
from importlib.util import find_spec
from importlib import reload
from os import system, stat
import weakref
import sys


def setup():
    if system('./setup.py clean build install') > 0:
        raise SystemError("Failed to setup python c-api extention class")


def main():
    if find_spec('custom2') is None:
        setup()
        for module_name in list(sys.modules.keys()):
            m = sys.modules.get(module_name)
            if not hasattr(m, '__file__'):
                continue
            if getattr(m, '__name__', None) in [None, '__mp_main__', '__main__']:
                continue

            try:
                # superreload(m)  # from ==> IPython.extensions
                # sys.modules[module_name] = reload(m)
                reload(m)
            except Exception as e:
                ...

    MyCustomExtended(1, 2, 3)
    print("COOL")


if __name__ == "__main__":
    main()

utils.my_custom_py.py

from importlib.util import find_spec

if find_spec('custom2'):
    import custom2
else:
    class custom2:
        class Custom:
            ...

class MyCustomExtended(custom2.Custom):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)

setup.py

from distutils.core import Extension, setup

custom_ext = Extension("custom2", ["src/custom.c"])
setup(name="custom2", version="1.0", ext_modules=[custom_ext])

src.custom.c 取自:docs.python.org

错误输出

running clean
running build
running build_ext
building 'custom2' extension
creating build
creating build/temp.linux-x86_64-3.6
creating build/temp.linux-x86_64-3.6/src
x86_64-linux-gnu-gcc -pthread -DNDEBUG -g -fwrapv -O2 -Wall -g -fstack-protector-strong -Wformat -Werror=format-security -Wdate-time -D_FORTIFY_SOURCE=2 -fPIC -I/tmp/PlayAround/.venv/include -I/usr/include/python3.6m -c src/custom.c -o build/temp.linux-x86_64-3.6/src/custom.o
creating build/lib.linux-x86_64-3.6
x86_64-linux-gnu-gcc -pthread -shared -Wl,-O1 -Wl,-Bsymbolic-functions -Wl,-Bsymbolic-functions -Wl,-z,relro -Wl,-Bsymbolic-functions -Wl,-z,relro -g -fstack-protector-strong -Wformat -Werror=format-security -Wdate-time -D_FORTIFY_SOURCE=2 build/temp.linux-x86_64-3.6/src/custom.o -o build/lib.linux-x86_64-3.6/custom2.cpython-36m-x86_64-linux-gnu.so
running install
running install_lib
copying build/lib.linux-x86_64-3.6/custom2.cpython-36m-x86_64-linux-gnu.so -> /tmp/PlayAround/.venv/lib/python3.6/site-packages
running install_egg_info
Removing /tmp/PlayAround/.venv/lib/python3.6/site-packages/custom2-1.0.egg-info
Writing /tmp/PlayAround/.venv/lib/python3.6/site-packages/custom2-1.0.egg-info
Traceback (most recent call last):
  File "./main.py", line 38, in <module>
    main()
  File "./main.py", line 33, in main
    MyCustomExtended(1, 2, 3)
  File "/tmp/PlayAround/utils/my_custom_py.py", line 12, in __init__
    super().__init__(*args, **kwargs)
TypeError: object.__init__() takes no parameters

主要工作

from importlib.util import find_spec
from importlib import reload
from os import system, stat
import weakref
import sys


def setup():
    if system('./setup.py clean build install') > 0:
        raise SystemError("Failed to setup python c-api extention class")


def main():
    if find_spec('custom2') is None:
        setup()

    from utils.my_custom_py import MyCustomExtended
    MyCustomExtended(1, 2, 3)
    print("COOL")


if __name__ == "__main__":
    main()

【问题讨论】:

  • 如果您的问题是关于重新加载模块,请创建一个脚本来加载和重新加载单个模块。
  • 这太简单了,需要预先步骤,这正是我试图避免的:),对于这种情况,python 语言必须有解决方案。
  • 我的意思是你的问题中有太多代码,我个人无法理解你想要的。
  • 这样,我完全同意,但我也在努力简化代码。我会再试一次。
  • 我想要实现的是检查是否安装了 Python C 扩展模块,如果是,则继续,如果没有安装,则重新加载模块,然后继续。

标签: python python-3.6


【解决方案1】:

最后,我通过反复试验找到了解决方案。 对于此示例代码 id 执行以下操作:

from utils.my_custom_py import MyCustomExtended
from importlib.util import find_spec
from importlib import reload
from sys import modules
from os import system


def setup():
    if system('./setup.py clean build install') > 0:
        raise SystemError("Failed to setup python c-api extention class")

def reload_my_libs():
    global MyCustomExtended
    reload(modules['utils'])
    reload(modules['utils.my_custom_py'])
    from utils.my_custom_py import MyCustomExtended


def main():
    if find_spec('custom2') is None:
        setup()
        reload_my_libs()

    MyCustomExtended(1, 2, 3)
    print("COOL")


if __name__ == "__main__":
    main()

结果,我得到了:

running clean
running build
running build_ext
building 'custom2' extension
creating build
creating build/temp.linux-x86_64-3.6
creating build/temp.linux-x86_64-3.6/src
x86_64-linux-gnu-gcc -pthread -DNDEBUG -g -fwrapv -O2 -Wall -g -fstack-protector-strong -Wformat -Werror=format-security -Wdate-time -D_FORTIFY_SOURCE=2 -fPIC -I/tmp/PlayAround/.venv/include -I/usr/include/python3.6m -c src/custom.c -o build/temp.linux-x86_64-3.6/src/custom.o
creating build/lib.linux-x86_64-3.6
x86_64-linux-gnu-gcc -pthread -shared -Wl,-O1 -Wl,-Bsymbolic-functions -Wl,-Bsymbolic-functions -Wl,-z,relro -Wl,-Bsymbolic-functions -Wl,-z,relro -g -fstack-protector-strong -Wformat -Werror=format-security -Wdate-time -D_FORTIFY_SOURCE=2 build/temp.linux-x86_64-3.6/src/custom.o -o build/lib.linux-x86_64-3.6/custom2.cpython-36m-x86_64-linux-gnu.so
running install
running install_lib
copying build/lib.linux-x86_64-3.6/custom2.cpython-36m-x86_64-linux-gnu.so -> /tmp/PlayAround/.venv/lib/python3.6/site-packages
running install_egg_info
Removing /tmp/PlayAround/.venv/lib/python3.6/site-packages/custom2-1.0.egg-info
Writing /tmp/PlayAround/.venv/lib/python3.6/site-packages/custom2-1.0.egg-info
COOL

它也适用于我以前的问题版本,但要复杂得多。

无论如何,感谢您的帮助:)

【讨论】:

  • 我会为以后遇到此类问题的人添加,以防您有比此示例更复杂的项目,因为此问题以前的版本或更高版本,重新加载顺序很重要。
【解决方案2】:

除了代码中的各种小问题外,您还试图重新加载现有的所有模块,同时默默地吞下错误。重新加载 utils 模块按预期工作:

import utils
from importlib.util import find_spec
from importlib import reload
from os import system, stat
import weakref
import sys


def setup():
    if system('python3 setup.py clean build install') > 0:
        raise SystemError("Failed to setup python c-api extention class")


def main():
    if find_spec('custom2') is None:
        setup()
        for module_name in list(sys.modules.keys()):
            m = sys.modules.get(module_name)
            if not hasattr(m, '__file__'):
                continue
            if getattr(m, '__name__', None) in [None, '__mp_main__', '__main__']:
                continue

        reload(utils)

    MyCustomExtended = utils.MyCustomExtended
    print(MyCustomExtended)
    MyCustomExtended(1, 2, 3)
    print("COOL")


if __name__ == "__main__":
    main()

我建议您只重新加载属于您应用程序一部分的模块。

【讨论】:

  • 我肯定知道的一件事,为了解决这个问题,如果它是可解决的,我需要了解import 究竟做了什么。
  • 我得到的结果与您的“工作”示例相匹配,更新您的问题以澄清。
  • 我更新了(或者为了更准确的问题而过于简单化了),因为你说过,我引用:“你的问题中有太多代码,我个人无法理解你想要的“,主要问题是我的第一个问题是重新加载的顺序
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-01-07
  • 1970-01-01
  • 1970-01-01
  • 2022-12-19
  • 1970-01-01
相关资源
最近更新 更多