我有一个创建文件的简单python函数:
kmer_counter.py
def counter(k):
list_kmer = []
freq = {}
reader = open("out/clean_read.txt", 'r')
while True:
line = reader.readline().rstrip()
if not line:
break
for i in range(0, len(line) - k + 1):
kmer = line[i : i + k]
if kmer in freq:
freq[kmer] += 1
else:
freq[kmer] = 1
reader.close()
freq = {key:val for key, val in freq.items() if val != 1}
writer = open("out/kmer.txt", 'w')
for key in freq.keys():
writer.write(key + '\n')
writer.close()
我尝试使用Python.h
头文件在C程序中调用它们。我没有任何类型的错误,但是在主文件末尾,未创建文件。
这是main.c
文件:
#include <stdio.h>
#include <stdlib.h>
#if defined(__APPLE__) || defined(__MACH__)
#include <Python/Python.h>
#elif defined(unix) || defined(__unix__) || defined(__unix)
#include <Python.h>
#include <stdint.h>
#endif
int main(void) {
Py_SetProgramName(argv[0]);
Py_Initialize();
PyObject* myModuleString = PyUnicode_FromString((char *) "kmer_counter");
PyObject* myModule = PyImport_Import(myModuleString);
PyObject* myFunction = PyObject_GetAttrString(myModule,(char *) "counter");
PyObject* args = PyUnicode_FromString("5");
PyObject *myResult = PyObject_CallFunctionObjArgs(myFunction, args);
Py_Finalize();
}
对于编译文件,我使用标志-I/usr/include/python2.7 -lpython2.7
。
我对此说法有不同的疑问,但我没有找到解决该问题的正确方法。
这是文件clean_read.txt
的内容:
ACCAG
CCAGTG
GTGAAC
CAGTGA
ACCAGT
TGAACG
GAACGGTA
CAGTGTA
AACGGTA
GAACGG
AGTGAACG
AACGGT
CAGTGAA
TGAACGGTA
我在PyObject_CallFunctionObjArgs
之后添加了以下代码行,但是它什么也没打印出来。
if (myResult) {
fputs("result: ", stderr);
PyObject_Print(myResult, stderr, 0);
putc('\n', stderr);
}
else {
fputs("exception:\n", stderr);
PyErr_PrintEx(0);
}
strace
在此link输出
将我的主要代码替换为第一个答案中的代码后,这是输出:
This is the report what it outputs:
main begins
Py_SetProgramName: ok
Py_Initialize: ok
PyUnicode_FromString('kmer_counter'): result: r
u'kmer_counter'
PyImport_Import(myModuleString): exception:
ImportError: No module named kmer_counter
答案 0 :(得分:2)
您的代码中至少有两个严重错误,也许还有更多。您需要检查所有正在调用的函数的返回值,否则会错过它们。
两个最明显的问题是:
NULL
要求的PyObject_CallFunctionObjArgs
标记;该调用必须传递NULL
的最终参数,以用作指示可变长度参数列表结束位置的标记。 PyObject *myResult = PyObject_CallFunctionObjArgs(myFunction, args);
应该是PyObject *myResult = PyObject_CallFunctionObjArgs(myFunction, args, NULL);
k
,该参数的使用方式显然希望它是Python int
,但是您正在显式构造Python str
;到达for i in range(0, len(line) - k + 1):
的那一刻,它将立即引发TypeError
。 PyObject* args = PyUnicode_FromString("5");
应该为PyObject* args = PyLong_FromLong(5);
,以产生正确的类型。在两种情况下,错误都发生在您未检查返回码的最终调用上;类型问题会绕过Python函数的其余部分而引发Python级异常,而varargs错误可能会导致无法预料的可怕事情。您需要更加严格地检查返回值,并且需要更加注意API要求。
旁注:在这种情况下,您可以使用PyObject_CallFunction
来替换相当数量的代码,包括所有不良代码,从而节省一些精力。所有这些:
PyObject* args = PyUnicode_FromString("5");
PyObject *myResult = PyObject_CallFunctionObjArgs(myFunction, args);
可以替换为:
PyObject *myResult = PyObject_CallFunction(myFunction, "i", 5);
这简化了工作(并减少了一个对象泄漏的对象的数量)。
看起来kmer_counter.py
既不在您的工作目录中,也不在sys.path
中的其他地方。如果从命令行运行,则最简单的解决方案是在运行可执行文件之前,cd
进入与kmer_counter.py
相同的目录(不必位于同一目录中)。另一个(有点怪异)的解决方案是创建/扩展PYTHONPATH
环境变量,以包含包含kmer_counter.py
的路径,例如在bash
中,您可以这样做(遵循your comment的路径):
PYTHONPATH=./src/prepros ./app
或作为两行(其中export
仅需要运行一次):
export PYTHONPATH=./src/prepros
./app
无论如何,只是为了让您了解正在执行的不必要工作量,这是将您的C代码简化为使用尽可能少的API调用(尽管使用zwol's check_PyAPI
可以简化错误检查在实际代码中,您可能要通过立即死亡并显示错误消息的方式来处理一些错误):
int main(void) {
Py_SetProgramName(argv[0]);
Py_Initialize();
// Load module without needing to construct PyUnicode manually
PyObject* myModule = PyImport_ImportModule("kmer_counter");
check_PyAPI("PyImport_ImportModule(\"kmer_counter\")", myModule);
// Call function on module without needing to construct PyUnicode
// or PyLong, and without needing to load the function itself
PyObject* myResult = PyObject_CallMethod(myModule, "counter", "i", 5);
Py_DECREF(myModule); // Done with module, release reference
check_PyAPI("PyObject_CallMethod(myModule, \"counter\", \"i\", 5)", myResult);
// Do whatever you want with successful result
Py_DECREF(myResult); // Done with result, release reference
Py_Finalize();
}
完成您在两个呼叫中进行的所有五个呼叫的工作(我还添加了Py_DECREF
来监视您的引用计数);当然,如果需要重新使用各种临时对象,那么有必要将它们临时化并反复使用它们,而不是让更高级别的函数一次又一次地重建PyUnicode
或继续在其中重新查找该函数。题。但是,当您刚入门时,请让Python为您做更多的工作。稍后进行优化(由于避免了字节码解释器的开销,您已经比Python级别的代码更快)。
答案 1 :(得分:1)
ShadowRanger的回答就目前而言是正确的,但是您的UIScreen
输出表明您的程序从未尝试打开任何名为if UIScreen.screens.count > 1 {
let externalScreen = UIScreen.screens[1]
print("Playing: externalScreen.bounds: \(externalScreen.bounds)")
let secondWindow = UIWindow(frame: externalScreen.bounds)
secondWindow.screen = externalScreen
let overlayImage = UIImage(named: "rain.png")
let overlayImageView = UIImageView(frame: externalScreen.bounds)
overlayImageView.image = overlayImage
secondWindow.addSubview(overlayImageView)
secondWindow.isHidden = false
secondWindow.makeKeyAndVisible()
}
的文件,这意味着问题发生的时间更早,甚至可能在{ {1}}。现在是时候应用一种更具攻击性的调试技术了:在strace
中记录每一个操作的结果。请用此代码替换整个测试程序,构建并运行它,并报告其输出。
kmer_counter.py