基于用户输入逻辑表达式过滤QTableWidget多条件失效问题排查
Let's break down why your current code fails with and/or combinations, then fix it step by step.
The Root Problem
Your existing condition if eval(self.filterTextbox.text()) in self.log[row]: misinterprets the user's logical input entirely:
- For an input like
'item1' or 'item2',eval()returns'item1'(sinceorreturns the first truthy value), then you only check if'item1'exists in the row—ignoring theor 'item2'clause. - For
'item1' and 'item2',eval()returns'item2', so you only verify if'item2'is present, not that both terms exist in the row.
You're treating the evaluated result as a single keyword to match, instead of checking if the full logical condition applies to the row's data.
The Solution
We need to rewrite the user's input to explicitly check each term against the current row's data. Here's the revised applyFilter function:
def applyFilter(self): filter_expr = self.filterTextbox.text().strip() if not filter_expr: self.showAllRows(self.log) return try: for row_idx in range(1, len(self.log)): row_data = self.log[row_idx] print(f'\nRow Content: {row_idx} {row_data}') # Rewrite user's expression to check each quoted term against the row # Handles single-quoted terms; adjust regex if you need double quotes import re parsed_expr = re.sub(r"'([^'\\]*(?:\\.[^'\\]*)*)'", r"'\1' in row_data", filter_expr) # Evaluate the fully formed logical condition matches = eval(parsed_expr) if matches: print('Row matches filter expression') self.tableWidget.showRow(row_idx - 1) else: print('Row does not match filter expression') self.tableWidget.hideRow(row_idx - 1) except (SyntaxError, NameError): # Fallback to showing all rows for invalid input self.showAllRows(self.log) print('Invalid filter expression—showing all rows')
How This Works
- Expression Parsing: The regex transforms every single-quoted term (e.g.,
'item1') into a check against the row data:- Input
'item1' or 'item2'becomes'item1' in row_data or 'item2' in row_data - Input
'item1' and 'item2'becomes'item1' in row_data and 'item2' in row_data
- Input
- Correct Condition Evaluation: Now
eval()returns a boolean (True/False) that tells us if the row meets the full logical criteria. - Robust Error Handling: Added
NameErrorto catch cases where users enter unquoted text (which would be treated as an undefined variable otherwise).
Critical Security Note
Using eval() with untrusted user input is unsafe—a malicious user could inject code to execute arbitrary commands. For production apps, consider safer alternatives like:
- Using
ast.literal_evalfor simple cases - Building a custom expression parser with libraries like
ply - Using a dedicated filter query language
Test Cases
- Input:
'error' and '2024'→ Shows rows containing both 'error' and '2024' - Input:
'warning' or 'info'→ Shows rows containing either 'warning' or 'info' - Input:
'critical'→ Works exactly like your original single-condition case (backward compatible)
内容的提问来源于stack exchange,提问作者vberiah

