在 python 中导入 nim seq

import nim seq in python

th.nim

import nimpy
import nimongo.bson
import nimongo.mongo


proc fib(): seq[Bson] {.exportpy.} =
  var m: Mongo = newMongo()
  let connected = m.connect()
  let col = m["feed"]["post"]
  var docs: seq[Bson]
  for document in col.find(%*{}).items():
    docs.add(document)

  return docs

main.py

import nimporter
import th

h = th.fib()
for item in h:
    print(item)

并且在第 123 行的 nimporter 模块中我添加了两个编译参数

'-d:nimOldCaseObjects', #because of an error
'--bound_checks:off', #because of an error

输出:

<capsule object NULL at 0x7f1975a47ae0>
<capsule object NULL at 0x7f1975a77d50>
<capsule object NULL at 0x7f1975a77f60>
<capsule object NULL at 0x7f19759488a0>
<capsule object NULL at 0x7f1975948840>
...

如何在 python 中获取像 dict 或 json 这样的数据结构?

PyCapsules 被定义为 here。您在 python 代码的胶囊中接收 Bson ref 对象,如果我理解正确的话,它们是 C 指针。您可以将代码修改为 return 字符串,或任何其他不是 ref 对象 的类型,这样它就可以工作了:

import nimpy
import nimongo / [bson, mongo]

proc fib*: seq[string] {.exportpy.} =
  let m = newMongo()
  if m.connect():
    let col = m["feed"]["post"]

    for document in col.find(%*{}).items():
      result.add($document)

在python中:

import nimporter
import th

for item in th.fib():
    print(item)

为了进一步说明,从 Nim 到 Python 的以下过程 return a Table:第一个是 Table,第二个是 ref Table.

import tables
import nimpy


proc objs*: Table[string, string] {.exportpy.} =
  {"Nim": "Awesome"}.toTable

proc refs*: TableRef[string, string] {.exportpy.} =
  {"Nim": "Awesome"}.newTable

import nimporter
import script as th


for k, v in th.objs().items():
    print(k, "is", v)

for k, v in th.refs().items():
    print(k, "is", v)

只有第一个有效,第二个正在收到您可能没有预料到的 PyCapsule

Nim is Awesome
Traceback (most recent call last):
  File "script.py", line 8, in <module>
    for k, v in th.refs().items():
TypeError: 'PyCapsule' object is not iterable

你需要将你得到的 bson 对象翻译成在 Python 世界中可用的东西。由于 nimpy 将 json 愉快地转换为 Python 字典,因此在 Nim 中进行转换是有意义的。

不幸的是,nimongo 没有实现 bson-json 转换,一个正确的答案是写那个 proc,但这里有一个占位符答案,通过将 bson 解码为字符串,然后编码即 json.

th.nim

import nimpy,nimongo/bson
from json import parseJson,JsonNode
#it's important here not to import the whole of json, as %* clashes

proc toJson*(bs:Bson):JsonNode = 
  parseJson($bs)

proc fib(): seq[JsonNode] {.exportpy.} =
  var docs = @[%*{
    "double": 5436.5436,
    "stringkey": "stringvalue",
    "document": {
      "double": 5436.5436,
      "key": "value"
    },
    "array": [1, 2, 3],
    "int32": 5436'i32,
    "int64": 5436,
  }]
  for doc in docs:
    result.add(doc.toJson)

输出

{'double': 5436.5436, 'stringkey': 'stringvalue', 'document': {'double': 5436.5436, 'key': 'value'}, 'array': [1, 2, 3], 'int32': 5436, 'int64': 5436}