2011-01-05 118 views
0

我在Python3中使用基於Python 2的C++引擎工作時遇到了一些嚴重的麻煩。我知道整個IO堆棧已經改變,但是我似乎嘗試的一切都以失敗告終。以下是預代碼(Python2)和後代碼(Python3)。我希望有人能幫我弄清楚我做錯了什麼。我也使用boost::python來控制參考。Python 3 C-API IO和文件執行

該程序假設經由映射到Python對象加載到存儲器中,然後在使用時的運行功能它然後發現在存儲器中加載的文件並運行它。我將我的代碼從delta3d python管理器的示例中提取出來,並將它們加載到文件中並立即運行。我在Python3中沒有看到任何相同的東西。


Python2代碼從這裏開始:

// what this does is first calls the Python C-API to load the file, then pass the returned 
    // PyObject* into handle, which takes reference and sets it as a boost::python::object. 
    // this takes care of all future referencing and dereferencing. 
    try{ 
     bp::object file_object(bp::handle<>(PyFile_FromString(fullPath(filename), "r"))); 
     loaded_files_.insert(std::make_pair(std::string(fullPath(filename)), file_object)); 
    } 
    catch(...) 
    { 
     getExceptionFromPy(); 
    } 

接下來,我從性病::地圖加載該文件,並試圖執行它:

bp::object loaded_file = getLoadedFile(filename); 
    try 
    { 
     PyRun_SimpleFile(PyFile_AsFile(loaded_file.ptr()), fullPath(filename)); 
    } 
    catch(...) 
    { 
     getExceptionFromPy(); 
    } 

Python3代碼從這裏開始:這是我迄今爲止基於這裏的一些建議... SO Question 加載:

 PyObject *ioMod, *opened_file, *fd_obj; 

     ioMod = PyImport_ImportModule("io"); 
     opened_file = PyObject_CallMethod(ioMod, "open", "ss", fullPath(filename), "r"); 

     bp::handle<> h_open(opened_file); 
     bp::object file_obj(h_open); 
     loaded_files_.insert(std::make_pair(std::string(fullPath(filename)), file_obj)); 

運行:

bp::object loaded_file = getLoadedFile(filename); 
    int fd = PyObject_AsFileDescriptor(loaded_file.ptr()); 
    PyObject* fileObj = PyFile_FromFd(fd,fullPath(filename),"r",-1,"", "\n","", 0); 

    FILE* f_open = _fdopen(fd,"r"); 

    PyRun_SimpleFile(f_open, fullPath(filename)); 

最後,在這一點上,程序的總體狀況是文件被加載在爲TextIOWrapper,並在運行:部分返回的fd是永遠3由於某種原因,_fdopen永遠不能打開FILE,這意味着我不能做類似PyRun_SimpleFile的事情。錯誤本身是_fdopen上的調試ASSERTION。有沒有更好的方法來做這一切,我真的很感謝任何幫助。

如果你想看到Github

+0

我在給你正在嘗試做的困惑。上面哪個Python 3示例應該取代上面的Python 2示例中的哪一個?他們都如此不同。你的實際錯誤信息是什麼? – 2011-01-05 15:37:14

+0

夠公平的,我做了一些編輯,並在第二段中解釋了我想要完成的事情。 – 2011-01-05 15:42:18

+0

我可能找到了解決方案,但我無法測試它,直到我回家。當我這樣做,我會發布它。 – 2011-01-05 20:35:32

回答

0

的Python2版本,它是完整的程序,所以這個問題是相當困難的理解,我很抱歉,但我發現我的舊代碼是不是很爲工作我期望。這就是我想要的代碼。將python文件加載到內存中,將其存儲到映射中,然後在內存中執行該代碼。我完成了這個比我預期的有點不同,但它現在很有意義。

  1. 打開使用ifstream的文件,請參見下面
  2. 代碼轉換的焦炭引入一個boost ::蟒蛇::海峽
  3. 用的boost ::蟒蛇執行的boost ::蟒蛇::海峽:: exec
  4. 獲利???

步驟1)

vector<char> input; 
ifstream file(fullPath(filename), ios::in); 
if (!file.is_open()) 
{ 
    // set our error message here 
    setCantFindFileError(); 
    input.push_back('\0'); 
    return input; 
} 

file >> std::noskipws; 
copy(istream_iterator<char>(file), istream_iterator<char>(), back_inserter(input)); 
input.push_back('\n'); 
input.push_back('\0'); 

步驟2) BP :: STR file_str(串(&輸入[0])); loaded_files_。插入(std :: make_pair(std :: string(fullPath(filename)),file_str)); 步驟3)

bp::str loaded_file = getLoadedFile(filename); 
// Retrieve the main module 
bp::object main = bp::import("__main__"); 
// Retrieve the main module's namespace 
bp::object global(main.attr("__dict__")); 
bp::exec(loaded_file, global, global); 

完整的代碼位於github