# Buggy code
def validate_expression(expr, variable_set, function_set=[], names=None):
    global last_func
    names = names if names is not None else []
    if isinstance(expr, six.string_types):
        node = ast.parse(expr)
        if len(node.body) != 1:
            raise ValueError("expected one expression, got %r" % len(node.body))
        first_expr = node.body[0]
        if not isinstance(first_expr, _ast.Expr):
            raise ValueError("expected an expression got a %r" % type(node.body))
        validate_expression(first_expr.value, variable_set, function_set, names)
    elif isinstance(expr, _ast.BinOp):
        if expr.op.__class__ in valid_binary_operators:
            validate_expression(expr.right, variable_set, function_set, names)
            validate_expression(expr.left, variable_set, function_set, names)
        else:
            raise ValueError("Binary operator not allowed: %r" % expr.op)
    elif isinstance(expr, _ast.UnaryOp):
        if expr.op.__class__ in valid_unary_operators:
            validate_expression(expr.operand, variable_set, function_set, names)
        else:
            raise ValueError("Unary operator not allowed: %r" % expr.op)
    elif isinstance(expr, _ast.Name):
        validate_id(expr.id)
        if expr.id not in variable_set:
            matches = difflib.get_close_matches(expr.id, list(variable_set))
            msg = "Column or variable %r does not exist." % expr.id
            if matches:
                msg += " Did you mean: " + " or ".join(map(repr, matches))

            raise NameError(msg)
        names.append(expr.id)
    elif isinstance(expr, ast_Num):
        pass  # numbers are fine
    elif isinstance(expr, ast_Str):
        pass  # as well as strings
    elif isinstance(expr, _ast.Call):
        validate_func(expr.func, function_set)
        last_func = expr
        for arg in expr.args:
            validate_expression(arg, variable_set, function_set, names)
        for arg in expr.keywords:
            validate_expression(arg, variable_set, function_set, names)
    elif isinstance(expr, _ast.Compare):
        validate_expression(expr.left, variable_set, function_set, names)
        for op in expr.ops:
            if op.__class__ not in valid_compare_operators:
                raise ValueError("Compare operator not allowed: %r" % op)
        for comparator in expr.comparators:
            validate_expression(comparator, variable_set, function_set, names)
    elif isinstance(expr, _ast.keyword):
        validate_expression(expr.value, variable_set, function_set, names)
    elif isinstance(expr, ast_Constant):
        pass  # like True and False
    elif isinstance(expr, _ast.Subscript):
        validate_expression(expr.value, variable_set, function_set, names)
        if isinstance(expr.slice.value, ast_Num):
            pass  # numbers are fine
        elif isinstance(expr.slice.value, _ast.Str):
            pass  # and strings
        else:
            raise ValueError(
                "Only subscript/slices with numbers allowed, not: %r" % expr.slice.value
            )
    else:
        last_func = expr
        raise ValueError("Unknown expression type: %r" % type(expr))


# Traceback (ValueError)
ValueError                                Traceback (most recent call last)
<ipython-input-59-b91ac46b6ba4> in <module>
----> 1 df.groupby(vaex.BinnerTime(df.字段1)).agg('count')

C:\ProgramData\anaconda3\lib\site-packages\vaex\groupby.py in __init__(self, expression, resolution, df, every)
57         self.begin_name = self.df.add_variable('t_begin', self.tmin.astype(self.resolution_type), unique=True)
58         # TODO: import integer from future?
---> 59         self.binby_expression = str(self.df['%s - %s' % (self.expression.astype(self.resolution_type), self.begin_name)].astype('int') // every)
60         self.binner = self.df._binner_ordinal(self.binby_expression, self.N)
61

C:\ProgramData\anaconda3\lib\site-packages\vaex\dataframe.py in __getitem__(self, item)
4585             # if item in self._virtual_expressions:
4586             #     return self._virtual_expressions[item]
-> 4587             self.validate_expression(item)
4588             return Expression(self, item)  # TODO we'd like to return the same expression if possible
4589         elif isinstance(item, Expression):

C:\ProgramData\anaconda3\lib\site-packages\vaex\dataframe.py in validate_expression(self, expression)
2899         funcs = set(expression_namespace.keys())  | set(self.functions.keys())
2900         try:
-> 2901             return vaex.expresso.validate_expression(expression, vars, funcs)
2902         except NameError as e:
2903             raise NameError(str(e)) from None

C:\ProgramData\anaconda3\lib\site-packages\vaex\expresso.py in validate_expression(expr, variable_set, function_set, names)
77                              type(node.body))
78         validate_expression(first_expr.value, variable_set,
---> 79                             function_set, names)
80     elif isinstance(expr, _ast.BinOp):
81         if expr.op.__class__ in valid_binary_operators:

C:\ProgramData\anaconda3\lib\site-packages\vaex\expresso.py in validate_expression(expr, variable_set, function_set, names)
81         if expr.op.__class__ in valid_binary_operators:
82             validate_expression(expr.right, variable_set, function_set, names)
---> 83             validate_expression(expr.left, variable_set, function_set, names)
84         else:
85             raise ValueError("Binary operator not allowed: %r" % expr.op)

C:\ProgramData\anaconda3\lib\site-packages\vaex\expresso.py in validate_expression(expr, variable_set, function_set, names)
108         last_func = expr
109         for arg in expr.args:
--> 110             validate_expression(arg, variable_set, function_set, names)
111         for arg in expr.keywords:
112             validate_expression(arg, variable_set, function_set, names)

C:\ProgramData\anaconda3\lib\site-packages\vaex\expresso.py in validate_expression(expr, variable_set, function_set, names)
91             raise ValueError("Unary operator not allowed: %r" % expr.op)
92     elif isinstance(expr, _ast.Name):
---> 93         validate_id(expr.id)
94         if expr.id not in variable_set:
95             matches = difflib.get_close_matches(expr.id, list(variable_set))

C:\ProgramData\anaconda3\lib\site-packages\vaex\expresso.py in validate_id(id)
570     for char in id:
571         if char not in valid_id_characters:
--> 572             raise ValueError("invalid character %r in id %r" % (char, id))

ValueError: invalid character '字' in id '字段1'

# Fixed code
def validate_expression(expr, variable_set, function_set=[], names=None):
    global last_func
    names = names if names is not None else []
    if isinstance(expr, six.string_types):
        node = ast.parse(expr)
        if len(node.body) != 1:
            raise ValueError("expected one expression, got %r" % len(node.body))
        first_expr = node.body[0]
        if not isinstance(first_expr, _ast.Expr):
            raise ValueError("expected an expression got a %r" % type(node.body))
        validate_expression(first_expr.value, variable_set, function_set, names)
    elif isinstance(expr, _ast.BinOp):
        if expr.op.__class__ in valid_binary_operators:
            validate_expression(expr.right, variable_set, function_set, names)
            validate_expression(expr.left, variable_set, function_set, names)
        else:
            raise ValueError("Binary operator not allowed: %r" % expr.op)
    elif isinstance(expr, _ast.UnaryOp):
        if expr.op.__class__ in valid_unary_operators:
            validate_expression(expr.operand, variable_set, function_set, names)
        else:
            raise ValueError("Unary operator not allowed: %r" % expr.op)
    elif isinstance(expr, _ast.Name):
        if expr.id not in variable_set:
            matches = difflib.get_close_matches(expr.id, list(variable_set))
            msg = "Column or variable %r does not exist." % expr.id
            if matches:
                msg += " Did you mean: " + " or ".join(map(repr, matches))

            raise NameError(msg)
        names.append(expr.id)
    elif isinstance(expr, ast_Num):
        pass  # numbers are fine
    elif isinstance(expr, ast_Str):
        pass  # as well as strings
    elif isinstance(expr, _ast.Call):
        validate_func(expr.func, function_set)
        last_func = expr
        for arg in expr.args:
            validate_expression(arg, variable_set, function_set, names)
        for arg in expr.keywords:
            validate_expression(arg, variable_set, function_set, names)
    elif isinstance(expr, _ast.Compare):
        validate_expression(expr.left, variable_set, function_set, names)
        for op in expr.ops:
            if op.__class__ not in valid_compare_operators:
                raise ValueError("Compare operator not allowed: %r" % op)
        for comparator in expr.comparators:
            validate_expression(comparator, variable_set, function_set, names)
    elif isinstance(expr, _ast.keyword):
        validate_expression(expr.value, variable_set, function_set, names)
    elif isinstance(expr, ast_Constant):
        pass  # like True and False
    elif isinstance(expr, _ast.Subscript):
        validate_expression(expr.value, variable_set, function_set, names)
        if isinstance(expr.slice.value, ast_Num):
            pass  # numbers are fine
        elif isinstance(expr.slice.value, _ast.Str):
            pass  # and strings
        else:
            raise ValueError(
                "Only subscript/slices with numbers allowed, not: %r" % expr.slice.value
            )
    else:
        last_func = expr
        raise ValueError("Unknown expression type: %r" % type(expr))