ImportError:File.so未定义的符号:PyInterpreterState_GetID

时间:2019-04-06 21:00:28

标签: python-3.x cython cythonize

对文件进行Cython化并通过导入运行时,会出现错误,提示在获取python解释器状态时存在问题。

删除诸如multiprocessing.start()的多处理代码;切换到Cython自己的prange()。

谷歌搜索错误意味着什么,自从我第一次遇到该错误(2年前)以来,没有一个讨论此问题的结果。

赛顿0.29.6 Python 3.7

使用

构建
pyhton3 setup.py build_ext --inplace

setup.py所在的地方

from distutils.core import setup
from distutils.extension import Extension
from Cython.Build import cythonize

ext_modules = [Extension("Logic", ["Logic.pyx"], extra_compile_args=['-Ofast'],)]
setup(name="Logic", ext_modules=cythonize("Logic.pyx"))

还有问题代码...预计会出现一小段错误,但是解释器状态不是其中之一。

import secrets
import os
import time
import Cython

cdef list race = ["Asian", "Black", "White"]
cdef list hair = ["Brown", "Brown", "Brown", "Brown", "Black", "Black", "Black", "Blond", "Blond", "Red"]
cdef list eyes = ["Brown", "Brown", "Brown", "Blue", "Blue", "Blue", "Green", "Green", "Grey", "Hazel"]
cdef list gender = ["Female", "Male", "Female", "Female", "Female", "Female", "Male", "Male", "Male", "Male", "Female", "Female", "Female", "Female", "Male", "Male", "Male", "Male", "Female", "Female", "Female", "Female", "Male", "Male", "Male", "Male", "Female", "Female", "Female", "Female", "Male", "Male", "Male", "Male", "Female", "Female", "Female", "Female", "Male", "Male", "Male", "Male", "Female", "Female", "Female", "Female", "Male", "Male", "Male", "Male", "Female", "Female", "Female", "Female", "Male", "Male", "Male", "Male", "Female", "Female", "Female", "Female", "Male", "Male", "Male", "Male", "Female", "Female", "Female", "Female", "Male", "Male", "Male", "Male", "Female", "Female", "Female", "Female", "Male", "Male", "Male", "Male", "Female", "Female", "Female", "Female", "Male", "Male", "Male", "Male", "Female", "Female", "Female", "Female", "Male", "Male", "Male", "Male", "X", "XXY"]
cdef long age_limit_elder = 115
cdef long weight_limit = 400
cdef long age_limit_adult = 60
cdef long age_limit_child = 18
cdef long weight_limit_infant = 15
cdef long age_limit_infant = 4
cdef long population = 4873057333
cdef long infant = 633497453  # 13%
cdef long child = 1461917200  # 30%
cdef long adult = 2095414652  # 43%
cdef long elder = 682228028  # 14%
cdef list infant_population = []
cdef list child_population = []
cdef list adult_population = []
cdef list elder_population = []

cdef list adult_race_pool = []

cpdef dict adult_generation(long adult=adult, long age_limit_adult=age_limit_adult, long weight_limit=weight_limit, list race=race, list hair=hair, list eyes=eyes, list gender=gender, long age_limit_child=age_limit_child):
    cdef long age_ = secrets.choice(range(age_limit_child, age_limit_adult))
    cdef long weight_ = secrets.choice(range(90, weight_limit))
    cdef str race_ = secrets.choice(race)
    cdef str hair_ = secrets.choice(hair)
    cdef str eyes_ = secrets.choice(eyes)
    cdef str gender_ = secrets.choice(gender)
    # adult_population.append({"AGE": age_, "WEIGHT": weight_, "RACE": race_, "HAIR": hair_, "EYES": eyes_, "GENDER": gender_})
    return {"AGE": age_, "WEIGHT": weight_, "RACE": race_, "HAIR": hair_, "EYES": eyes_, "GENDER": gender_}

# adult_generation()
# cdef long adult_processes = adult // 4
# adult_processes = 10000
# cdef long adult_processes = 100000
cdef long adult_processes = adult  # Fallback
cdef long adult_percent = adult_processes // 10000
cdef double percent = 0
cdef long current = 0
cdef double t1 = time.time()
cdef double master = t1
cdef long i

for i in Cython.parallel.prange(adult_processes, nogil=True):
    if current == adult_percent:
        percent += 0.01
        t2 = time.time()
        t3 = t2 - t1
        os.system("tput reset")
        print(f"{percent}% Complete | {current} Profiles in {t3} Seconds")
        current = 0
        t1 = time.time()
    adult_population.append(adult_generation())
    current += 1

cdef long F = 0
cdef long M = 0
cdef long X = 0
cdef long XXY = 0

cdef dict item

for item in adult_population:
    if item["GENDER"] == "Female":
        F += 1
    elif item["GENDER"] == "Male":
        M += 1
    elif item["GENDER"] == "X":
        X += 1
    elif item["GENDER"] == "XXY":
        XXY += 1
    else:
        pass


print(f"FEMALE: {F}")
print(f"MALE: {M}")
print(f"X: {X}")
print(f"XXY: {XXY}")
print(f"Total Time: {time.time() - master} Seconds")

结果应该只是一个庞大的伪随机变量列表,就像在Python版本中那样,但在所有线程/内核上都没有奇数的70%CPU限制。

但是,在Cython中,当进行并行或多进程处理时,它在导入时返回“未定义符号:PyInterpreterState_GetID”,并退出。

使用较小的数字进行测试,因为当前数字需要146天的处理时间...更改结果数仍会产生错误。

人们也希望它挂在“ cdef dict项目”上,但是再一次,它甚至都无法解决。

1 个答案:

答案 0 :(得分:-2)

我不能说这是一个确定的答案,但是,我注意到Python错误输出非常短。我花了一点时间,然后赌博,将Cython代码直接编译成嵌入式程序包。这个程序包提供了完整的错误输出,即使它一团糟,它仍然可以引导到某个地方。

解释器状态似乎与线程/多处理有关,因此我对该部分进行了调整,并发现错误输出在抱怨GIL。显然,给Python的错误是来自Cython的,但是直到编译为独立的“ C”应用程序时才向用户显示。

此错误似乎集中在GIL周围,输出抱怨它无法从需要GIL的函数中删除GIL,即除返回,收益,打印,简单数学等以外的所有Python代码。 ..

因此,prange及其并行功能对于想要增强纯Python脚本的人来说几乎是无用的。由于任何依赖def,open,threading / multiprocessing模块的东西,或者实际上是任何Pythonic的东西,都会产生此错误,并且如果使用它的那个通过Python导入来测试其Cython代码,则它们只会陷入死胡同,一个google搜索结果中没有出现的行错误。

要解决prange错误,需要重写C中正在与之交互的全部内容,或者导入使用C而不是Python的内容。这再次使它对纯Python开发人员而言不再有用。

最后,我跳到了map函数,该函数允许进行多处理,而不会产生太多进程的开销(最后将达到30亿)。