使用functools.部分为pdfquery获取属性创建自定义筛选器

2024-09-30 16:42:29 发布

您现在位置:Python中文网/ 问答频道 /正文

背景

我使用pdfquery来解析多个文件,比如this one。你知道吗

问题

我正在尝试编写一个通用的文件管理器函数,它基于pdfquery's docs中提到的自定义选择器,可以将特定的范围作为参数。因为this是被引用的,所以我想我可以通过使用functools.partial提供一个分部函数来解决这个问题(如下所示)

输入

import pdfquery
import functools

def load_file(PDF_FILE):
    pdf = pdfquery.PDFQuery(PDF_FILE)
    pdf.load()
    return pdf

file_with_table = 'Path to the file mentioned above'
pdf = load_file(file_with_table)


def elements_in_range(x1_range):
    return in_range(x1_range[0], x1_range[1], float(this.get('x1',0)))

x1_part = functools.partial(elements_in_range, (95,350))

pdf.pq('LTPage[page_index="0"] *').filter(x1_part)

但是当我这样做的时候,我得到以下属性错误

输出

---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
C:\Anaconda3\lib\site-packages\pyquery\pyquery.py in filter(self, selector)
    597                     if len(args) == 1:
--> 598                         func_globals(selector)['this'] = this
    599                     if callback(selector, i, this):

C:\Anaconda3\lib\site-packages\pyquery\pyquery.py in func_globals(f)
     28 def func_globals(f):
---> 29     return f.__globals__ if PY3k else f.func_globals
     30 

AttributeError: 'functools.partial' object has no attribute '__globals__'

During handling of the above exception, another exception occurred:

AttributeError                            Traceback (most recent call last)
<ipython-input-74-d75c2c19f74b> in <module>()
     15 x1_part = functools.partial(elements_in_range, (95,350))
     16 
---> 17 pdf.pq('LTPage[page_index="0"] *').filter(x1_part)

C:\Anaconda3\lib\site-packages\pyquery\pyquery.py in filter(self, selector)
    600                         elements.append(this)
    601             finally:
--> 602                 f_globals = func_globals(selector)
    603                 if 'this' in f_globals:
    604                     del f_globals['this']

C:\Anaconda3\lib\site-packages\pyquery\pyquery.py in func_globals(f)
     27 
     28 def func_globals(f):
---> 29     return f.__globals__ if PY3k else f.func_globals
     30 
     31 

AttributeError: 'functools.partial' object has no attribute '__globals__'

有什么办法可以解决这个问题吗?或者用其他方法为pdfquery编写一个可以接受参数的自定义选择器?你知道吗


Tags: inifpdfdefrangethispartialselector
2条回答

仅仅使用一个函数返回一个新函数(类似于functools.部分但是用闭包代替?你知道吗

import pdfquery

def load_file(PDF_FILE):
    pdf = pdfquery.PDFQuery(PDF_FILE)
    pdf.load()
    return pdf

file_with_table = './RG234621_90110.pdf'
pdf = load_file(file_with_table)

def in_range(x1, x2, sample):
    return x1 <= sample <= x2

def in_x_range(bounds):
    def wrapped(*args, **kwargs):
        x = float(this.get('x1', 0))
        return in_range(bounds[0], bounds[1], x)
    return wrapped

def in_y_range(bounds):
    def wrapped(*args, **kwargs):
        y = float(this.get('y1', 0))
        return in_range(bounds[0], bounds[1], y)
    return wrapped


print(len(pdf.pq('LTPage[page_index="0"] *').filter(in_x_range((95, 350))).filter(in_y_range((60, 100)))))

# Or, perhaps easier to read

x_check = in_x_range((95, 350))
y_check = in_y_range((60, 100))

print(len(pdf.pq('LTPage[page_index="0"] *').filter(x_check).filter(y_check)))

输出

1
16 # <  bounds check is larger for y in this test

可以对正在比较的属性进行事件参数化

import pdfquery

def load_file(PDF_FILE):
    pdf = pdfquery.PDFQuery(PDF_FILE)
    pdf.load()
    return pdf

file_with_table = './RG234621_90110.pdf'
pdf = load_file(file_with_table)

def in_range(prop, bounds):
    def wrapped(*args, **kwargs):
        n = float(this.get(prop, 0))
        return bounds[0] <= n <= bounds[1]
    return wrapped


print(len(pdf.pq('LTPage[page_index="0"] *').filter(in_range('x1', (95, 350))).filter(in_range('y1', (60, 100)))))

x_check = in_range('x1', (95, 350))
y_check = in_range('y1', (40, 100))

print(len(pdf.pq('LTPage[page_index="0"] *').filter(x_check).filter(y_check)))

我还建议使用parse_tree_cacher参数,因为它加快了我找到合适解决方案的时间(尽管您可能不需要像我在解决这个问题时那样频繁地重新处理)。你知道吗

import pdfquery
from pdfquery.cache import FileCache

def load_file(PDF_FILE):
    pdf = pdfquery.PDFQuery(PDF_FILE, parse_tree_cacher=FileCache("/tmp/"))
    pdf.load()
    return pdf

尽管我喜欢闭包方法,但我确实应该提到,您可以将属性从包装函数复制到包装器。你知道吗

from functools import update_wrapper

custom_filter = update_wrapper(
    partial(
        elements_in_range, (95, 20)
    ),
    wrapped=elements_in_range,
    assigned=('__globals__', '__code__')
)

相关问题 更多 >