将Tcl列表转换为Python列表

将Tcl列表转换为Python列表,python,list,tcl,Python,List,Tcl,我尝试将Tcl列表转换为python列表 有两个问题: 如果原始列表中的列表仅包含一个列表,则翻译不正确。例如,{{12 34}未正确翻译 将所有数字转换为类型的选项无效 Python 3代码: import tkinter class TclInterpreter(object): def __init__(self): self._tcl = tkinter.Tcl() def eval(self, tcl_cmd): return

我尝试将Tcl列表转换为python列表

有两个问题:

  • 如果原始列表中的列表仅包含一个列表,则翻译不正确。例如,
    {{12 34}
    未正确翻译
  • 将所有数字转换为类型的选项无效
Python 3代码:

import tkinter


class TclInterpreter(object):
    def __init__(self):
        self._tcl = tkinter.Tcl()

    def eval(self, tcl_cmd):
        return self._tcl.eval(tcl_cmd)


class TclPyListTranslator(object):
    def __init__(self, tcl):
        self._tcl = tcl

    def to_py(self, tcl_list, dtype=str):
        # convert a Tcl List to python list, also convert elements of each leaf
        # node to dtype
        self._tcl.eval("set tcl_list %s" % tcl_list)
        numItems = int(self._tcl.eval("llength $tcl_list"))
        if numItems > 1:
            result = [self._tcl.eval("lindex $tcl_list %d" % i) for i in range(
                numItems)]
            for i in range(numItems):
                result[i] = self.to_py("{" + result[i] + "}", dtype)
        else:
            result = dtype(self._tcl.eval("lindex $tcl_list %d" % 0))
        return result


inter = TclInterpreter()
translator = TclPyListTranslator(inter)
tcl_list = "{12 {{12 34}} {56 {78 {11 12} 10}}}"

# prints ['12', '12 34', ['56', ['78', ['11', '12'], '10']]]
# The '12 34' is incorrect
print(translator.to_py(tcl_list))

# does not run
print(translator.to_py(tcl_list, int))

处理这个问题最简单的方法是让Tcl端的代码(它本机理解Tcl列表)生成Python值的字符串形式,然后在Python中
eval
。然而,复杂的部分是Tcl的类型系统与Python的类型系统完全不同(我不打算对此进行解释,因为这是一个非常复杂和技术性的论证),这使得决定嵌套列表结构的叶子在哪里变得非常重要。需要一些假设。有了这些假设,我们可以用不太多的代码完成相当不错的工作

您需要的Tcl端代码是这样的(在需要整数的叶子的情况下):

proc toPythonList{value}{
如果{[字符串为整数-严格的$value]}{
返回$value
}
设置结果“\[”
每件物品$value{
追加结果[toPythonList$item],“
}
追加结果“\]”
返回$result
}
这就意味着你可以做到这一点(我已经为不同类型的叶子添加了一个非常简单的适应版本):

类TcpylistTranslator(对象): 定义初始化(自我,tcl): self.\u tcl=tcl 自我评估(“自我评估”) proc isLeaf.int{value}{ 字符串是整数-严格的$value } proc isLeaf.str{value}{ expr{![字符串匹配“{*}”$value]} } proc toPythonLeaf.int{value}{return$value} proc toPythonLeaf.str{value}{返回“\”$value\”} proc toPythonList{value dtype}{ 如果{[isLeaf.$dtype$value]}{ 返回[toPythonLeaf.$dtype$value] } 设置结果“\[” 每件物品$value{ 追加结果[toPythonList$item],“ } 追加结果“\]” 返回$result } """) def to_py(self,tcl_list,dtype=str): #将Tcl列表转换为python列表 返回eval(self.\u tcl.eval(“toPythonList%s%s”%(tcl\u列表,数据类型.\u名称)) 警告:上面的代码应该可以运行,但我无法测试它,因为我没有在任何Python解释器中配置tkinter。不过这些代码可以独立运行,所以我有足够的信心。

Python解析器:

def add_element(cache, element):
    if element != '':
        cache[-1].append(element)
    return ''

def parse(raw_tcl_list):    
    out = []
    cache = [out]
    element = ''
    escape = False
    for char in tcl_list:
        if escape:
            element += char
            escape = False
        elif char == "\\":
            escape = True
        elif char in [" ", "\t", "\r", "\n"]:
            element = add_element(cache, element)
        elif char == "{":
            a = []
            cache[-1].append(a)
            cache.append(a)
        elif char == "}":
            element = add_element(cache, element)
            cache.pop()
        else:
            element += char
    return out[0]
import pprint
pprint.pprint(
    parse("{ 12 apple {100} {} {{12 34}} \n {56\n { \\{78 {11 12 11} 10}}}"))
输出:

['12',
 'apple',
 ['100'],
 [],
 [['12', '34']],
 ['56', ['{78', ['11', '12', '11'], '10']]]

你知道叶子是数字吗?或者你必须处理像字符串这样的事情吗这是一个尴尬的例子。有时我知道,有时我不知道。所以我把它作为一个选项。如果数据类型设置为int,那么我希望叶子都是数字。否则,我就把叶子节点作为字符串。
“{12{{12 34}}{56{78{11 12}10}}}}。替换(“{”、“[”)。替换(“}”、“]”)。替换(“,”)。替换(“\t”、“,”)。替换(“\”、“,”)
to literal\u eval.may be tkinter是个坏主意。@dsgdfg双空格将打断该选项,但我们希望类似的事情不会出现。列表中是否可以有任意深度的子列表集?向代码中添加对更多类型的支持只是一个练习。请注意,Tcl和Python之间还有其他可能让您感到困惑的差异还有,比如布尔常量之间的差异和字典的不同概念。我的代码不是通用的!我试图翻译一个只有整数的tcl列表。但是它不能区分叶子。
put[toPythonList{12{100}{{12 34}}{56{78{11 12 11}10}}}]
给出了
[12,100,[[12,34,],[56,[78,[11, 12, 11, ], 10, ], ], ]
最好将
eval
替换为
ast.literal\u eval
,因为您只需要解析,而不需要实际的评估。这降低了在
toPythonList
@rxu中可能出现错误时的安全风险如果您想要更复杂的东西,您可能必须从wri开始这是TDD真正发挥作用的地方。我刚刚编写了一个python解析器,它似乎可以工作。我对Tcl的了解还不够,不知道我是否遗漏了任何关键案例。