欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

從C語(yǔ)言中讀取Python 類(lèi)文件對(duì)象

 更新時(shí)間:2020年07月30日 15:43:05   作者:David Beazley  
這篇文章主要介紹了如何從C語(yǔ)言中讀取Python 類(lèi)文件對(duì)象,文中講解非常細(xì)致,代碼幫助大家更好的理解和學(xué)習(xí),感興趣的朋友可以了解下

問(wèn)題

你要寫(xiě)C擴(kuò)展來(lái)讀取來(lái)自任何Python類(lèi)文件對(duì)象中的數(shù)據(jù)(比如普通文件、StringIO對(duì)象等)。

解決方案

要讀取一個(gè)類(lèi)文件對(duì)象的數(shù)據(jù),你需要重復(fù)調(diào)用 read() 方法,然后正確的解碼獲得的數(shù)據(jù)。

下面是一個(gè)C擴(kuò)展函數(shù)例子,僅僅只是讀取一個(gè)類(lèi)文件對(duì)象中的所有數(shù)據(jù)并將其輸出到標(biāo)準(zhǔn)輸出:

#define CHUNK_SIZE 8192

/* Consume a "file-like" object and write bytes to stdout */
static PyObject *py_consume_file(PyObject *self, PyObject *args) {
 PyObject *obj;
 PyObject *read_meth;
 PyObject *result = NULL;
 PyObject *read_args;

 if (!PyArg_ParseTuple(args,"O", &obj)) {
  return NULL;
 }

 /* Get the read method of the passed object */
 if ((read_meth = PyObject_GetAttrString(obj, "read")) == NULL) {
  return NULL;
 }

 /* Build the argument list to read() */
 read_args = Py_BuildValue("(i)", CHUNK_SIZE);
 while (1) {
  PyObject *data;
  PyObject *enc_data;
  char *buf;
  Py_ssize_t len;

  /* Call read() */
  if ((data = PyObject_Call(read_meth, read_args, NULL)) == NULL) {
   goto final;
  }

  /* Check for EOF */
  if (PySequence_Length(data) == 0) {
   Py_DECREF(data);
   break;
  }

  /* Encode Unicode as Bytes for C */
  if ((enc_data=PyUnicode_AsEncodedString(data,"utf-8","strict"))==NULL) {
   Py_DECREF(data);
   goto final;
  }

  /* Extract underlying buffer data */
  PyBytes_AsStringAndSize(enc_data, &buf, &len);

  /* Write to stdout (replace with something more useful) */
  write(1, buf, len);

  /* Cleanup */
  Py_DECREF(enc_data);
  Py_DECREF(data);
 }
 result = Py_BuildValue("");

 final:
 /* Cleanup */
 Py_DECREF(read_meth);
 Py_DECREF(read_args);
 return result;
}

要測(cè)試這個(gè)代碼,先構(gòu)造一個(gè)類(lèi)文件對(duì)象比如一個(gè)StringIO實(shí)例,然后傳遞進(jìn)來(lái):

>>> import io
>>> f = io.StringIO('Hello\nWorld\n')
>>> import sample
>>> sample.consume_file(f)
Hello
World
>>>

討論

和普通系統(tǒng)文件不同的是,一個(gè)類(lèi)文件對(duì)象并不需要使用低級(jí)文件描述符來(lái)構(gòu)建。 因此,你不能使用普通的C庫(kù)函數(shù)來(lái)訪問(wèn)它。 你需要使用Python的C API來(lái)像普通文件類(lèi)似的那樣操作類(lèi)文件對(duì)象。

在我們的解決方案中,read() 方法從被傳遞的對(duì)象中提取出來(lái)。 一個(gè)參數(shù)列表被構(gòu)建然后不斷的被傳給 PyObject_Call() 來(lái)調(diào)用這個(gè)方法。 要檢查文件末尾(EOF),使用了 PySequence_Length() 來(lái)查看是否返回對(duì)象長(zhǎng)度為0.

對(duì)于所有的I/O操作,你需要關(guān)注底層的編碼格式,還有字節(jié)和Unicode之前的區(qū)別。 本節(jié)演示了如何以文本模式讀取一個(gè)文件并將結(jié)果文本解碼為一個(gè)字節(jié)編碼,這樣在C中就可以使用它了。 如果你想以二進(jìn)制模式讀取文件,只需要修改一點(diǎn)點(diǎn)即可,例如:

...
/* Call read() */
if ((data = PyObject_Call(read_meth, read_args, NULL)) == NULL) {
 goto final;
}

/* Check for EOF */
if (PySequence_Length(data) == 0) {
 Py_DECREF(data);
 break;
}
if (!PyBytes_Check(data)) {
 Py_DECREF(data);
 PyErr_SetString(PyExc_IOError, "File must be in binary mode");
 goto final;
}

/* Extract underlying buffer data */
PyBytes_AsStringAndSize(data, &buf, &len);
...

本節(jié)最難的地方在于如何進(jìn)行正確的內(nèi)存管理。 當(dāng)處理 PyObject * 變量的時(shí)候,需要注意管理引用計(jì)數(shù)以及在不需要的變量的時(shí)候清理它們的值。 對(duì) Py_DECREF() 的調(diào)用就是來(lái)做這個(gè)的。

本節(jié)代碼以一種通用方式編寫(xiě),因此他也能適用于其他的文件操作,比如寫(xiě)文件。 例如,要寫(xiě)數(shù)據(jù),只需要獲取類(lèi)文件對(duì)象的 write() 方法,將數(shù)據(jù)轉(zhuǎn)換為合適的Python對(duì)象 (字節(jié)或Unicode),然后調(diào)用該方法將輸入寫(xiě)入到文件。

最后,盡管類(lèi)文件對(duì)象通常還提供其他方法(比如readline(), read_info()), 我們最好只使用基本的 read() write() 方法。 在寫(xiě)C擴(kuò)展的時(shí)候,能簡(jiǎn)單就盡量簡(jiǎn)單。

以上就是從C語(yǔ)言中讀取Python 類(lèi)文件對(duì)象的詳細(xì)內(nèi)容,更多關(guān)于C語(yǔ)言中讀取Python類(lèi)文件的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • 探究一下C語(yǔ)言生成隨機(jī)數(shù)的奧秘

    探究一下C語(yǔ)言生成隨機(jī)數(shù)的奧秘

    C語(yǔ)言中生成隨機(jī)數(shù)是一項(xiàng)非常重要的功能,因?yàn)樵S多現(xiàn)代應(yīng)用程序需要使用隨機(jī)數(shù)。本文就來(lái)帶大家一起探究一下C語(yǔ)言生成隨機(jī)數(shù)的奧秘吧
    2023-03-03
  • 基于Matlab LBP實(shí)現(xiàn)植物葉片識(shí)別功能

    基于Matlab LBP實(shí)現(xiàn)植物葉片識(shí)別功能

    局部二值模式(LBP)是由Ojala等人于2002年提出,它被用于特征提取,而且提取的特征是圖像的紋理特征。本文將利用Matlab和LBP實(shí)現(xiàn)植物葉片識(shí)別,需要的可以參考一下
    2022-02-02
  • C++控制臺(tái)用定時(shí)器實(shí)例代碼

    C++控制臺(tái)用定時(shí)器實(shí)例代碼

    這篇文章主要介紹了C++控制臺(tái)用定時(shí)器實(shí)例代碼,分享了相關(guān)代碼示例,小編覺(jué)得還是挺不錯(cuò)的,具有一定借鑒價(jià)值,需要的朋友可以參考下
    2018-02-02
  • C語(yǔ)言實(shí)現(xiàn)單位車(chē)輛調(diào)度管理

    C語(yǔ)言實(shí)現(xiàn)單位車(chē)輛調(diào)度管理

    這篇文章主要為大家詳細(xì)介紹了C語(yǔ)言實(shí)現(xiàn)單位車(chē)輛調(diào)度管理,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2022-03-03
  • 15種?C++?常見(jiàn)報(bào)錯(cuò)原因分析

    15種?C++?常見(jiàn)報(bào)錯(cuò)原因分析

    這篇文章主要介紹了15種?C++?常見(jiàn)報(bào)錯(cuò),本文通過(guò)實(shí)例代碼給大家講解的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2023-01-01
  • C++繼承與菱形繼承詳細(xì)介紹

    C++繼承與菱形繼承詳細(xì)介紹

    繼承(inheritance)機(jī)制是面向?qū)ο蟪绦蛟O(shè)計(jì)使代碼可以復(fù)用的最重要的手段,它允許程序員在保持原有類(lèi)特性的基礎(chǔ)上進(jìn)行擴(kuò)展,增加功能,這樣產(chǎn)生新的類(lèi),稱(chēng)派生類(lèi)。繼承呈現(xiàn)了面向?qū)ο蟪绦蛟O(shè)計(jì)的層次結(jié)構(gòu),體現(xiàn)了由簡(jiǎn)單到復(fù)雜的認(rèn)知過(guò)程
    2022-08-08
  • VC實(shí)現(xiàn)批量刪除指定文件的方法

    VC實(shí)現(xiàn)批量刪除指定文件的方法

    這篇文章主要介紹了VC實(shí)現(xiàn)批量刪除指定文件的方法,是一個(gè)比較普遍且實(shí)用的功能,需要的朋友可以參考下
    2014-07-07
  • C++ Eigen庫(kù)計(jì)算矩陣特征值及特征向量

    C++ Eigen庫(kù)計(jì)算矩陣特征值及特征向量

    這篇文章主要為大家詳細(xì)介紹了C++ Eigen庫(kù)計(jì)算矩陣特征值及特征向量,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2019-06-06
  • C++20中的結(jié)構(gòu)化綁定類(lèi)型示例詳解

    C++20中的結(jié)構(gòu)化綁定類(lèi)型示例詳解

    這篇文章主要為大家介紹了C++20中的結(jié)構(gòu)化綁定類(lèi)型示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-04-04
  • C/C++的文件IO函數(shù)你知道嗎

    C/C++的文件IO函數(shù)你知道嗎

    這篇文章主要為大家詳細(xì)介紹了C/C++的文件IO函數(shù),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來(lái)幫助
    2022-03-03

最新評(píng)論