对 python 和编码来说相对较新,但我想我已经把头撞在墙上了,足以应对这个问题了。我来 Stack Overflow 寻求明智的建议。
我正在编写一个程序,它将在目标文件夹中搜索存储在“keyterms.csv”中的预定义术语。 keyterms.csv 有一列由换行符分隔的单词和短语,没有其他内容。当在目标目录中的文件中找到关键字术语文件中的单词或短语时,程序会返回罪魁祸首文件的名称以及找到的关键字术语的条目数。
Traceback (most recent call last):
count = len(re.findall(self.ktxt, ttxt))
TypeError: unhashable type: 'dict'
所以我认为答案很明显,re.findall 只适用于字符串或仅输出字符串的东西,而不适用于字典、列表或其他类似的东西。我尝试了 SO 中的几个代码片段,将读取的文件分割成单独的字符串以输入 re.findall,但无济于事。我应该将字符串输入到数组或其他东西中,然后 for.each 数组吗?不知道我到底错过了什么。
无视我大量的打印语句,只是用它们来追踪正在发生的事情。
据我所知,def read_key
和def find
是问题所在。我尝试过以多种方式拆分 self.ktxt = list(reader)
介绍字符串并将其发送到 def find
,但也许我根本不明白它是怎么回事。
import os
import re
import csv
class FindKterms:
def __init__(self, path, query):
self.path = path
self.query = query
self.ktxt = {}
self.searched = {}
print('def init complete ...')
def read_key(self):
print('opening keyterms.csv')
with open(self.query, newline='', encoding='utf_8') as f:
reader = csv.reader(f, delimiter='\n')
self.ktxt = list(reader)
def find(self):
if self.path[-1] != '/':
self.path += '/'
print('Appended "/" to given filepath')
print('starting find function ...')
for root, dirs, files in os.walk(self.path):
for file in files:
print('Searching: ' + file + ' ...')
f = open(root + file)
ttxt = f.read()
f.close()
print('successfully read and closed ' + file)
count = len(re.findall(self.ktxt, ttxt))
if count > 0:
self.searched[root + file] = count
def get_results(self):
return self.searched
main()
似乎可以很好地调用函数并移动数据。正在调用函数并且似乎可以正常工作。只需将 keyterms.csv 中的字符串用作目标目录中 re.findall 的匹配案例即可。
感谢您的任何帮助,我觉得我就在那里,但解决方案却让我困惑。
虽然 keyterms.csv 具有 .csv 扩展名,但没有理由将其视为 CSV 文件,因为它每行只有一个单词(术语)。因此,您可以打开它,一次读取一行并构建您的查询(正则表达式)。
假设我们有如下所示的 keyterms.csv:
ghi
xyz
abc
然后,在名为 data 的目录中,我们有 3 个文件 - a.txt、b.txt 和 c.txt,其内容如下:
ghi
ghi
abc
zzz
ghi
abc
abc
zzz
ppp
现在课程可以如下:
import re
from pathlib import Path
from collections import Counter
class FindKterms:
def __init__(self, path: Path, query: Path):
self._path = path # directory to be searched
self._query = query # file containing list of terms to be searched for
assert self._path.exists() and self._path.is_dir()
assert self._query.exists() and self._query.is_file()
@property
def terms(self) -> re.Pattern:
if not hasattr(self, "_terms"):
with self.query.open() as q:
qt = {line.strip() for line in q}
self._terms = re.compile("(" + "|".join(qt) + ")")
return self._terms
@property
def path(self) -> Path:
return self._path
@property
def query(self) -> Path:
return self._query
def process(self) -> dict[str, Counter]:
result = {}
for file in self.path.glob("*"):
with file.open() as fd:
if f := self.terms.findall(fd.read()):
result[file.name] = Counter(f)
return result
path = Path("~/data").expanduser()
query = Path("~/keyterms.csv").expanduser()
print(FindKterms(path, query).process())
输出:
{'b.txt': Counter({'abc': 2, 'ghi': 1}), 'a.txt': Counter({'ghi': 2, 'abc': 1})}
因此我们可以看到b.txt有2个'abc'和1个'ghi',a.txt有2个'ghi'和1个'abc'。文件 c.txt 确实出现在输出中,因为它不包含任何关键术语