在Python中跨不同文件调用变量并处理循环导入

在Python中跨不同文件调用变量并处理循环导入,python,Python,我目前正在用Python构建一个docx/pdf转换器,并决定将文件拆分为两个文档: main.py-控制程序的流程 convert_to_text.py-包含将pdf/docx文件转换为txt的函数 目前,我很难在两个文件之间传递全局变量cv,也很难将convert\u to_text.py中的所有函数导入main.py中使用。这是我得到的错误: C:\Python27\python.exe D:/cv-parser/main.py Traceback (most recent call la

我目前正在用Python构建一个docx/pdf转换器,并决定将文件拆分为两个文档:

main.py
-控制程序的流程

convert_to_text.py
-包含将pdf/docx文件转换为txt的函数

目前,我很难在两个文件之间传递全局变量
cv
,也很难将
convert\u to_text.py
中的所有函数导入
main.py
中使用。这是我得到的错误:

C:\Python27\python.exe D:/cv-parser/main.py
Traceback (most recent call last):
  File "D:/cv-parser/main.py", line 1, in <module>
    from convert_to_text import *
  File "D:\cv-parser\convert_to_text.py", line 1, in <module>
    from main import cv
  File "D:\cv-parser\main.py", line 5, in <module>
    document_to_text("resources\CV.pdf")
NameError: name 'document_to_text' is not defined

Process finished with exit code 1
main.py中

from main import cv
import docx
from pdfminer.pdfinterp import PDFResourceManager, PDFPageInterpreter
from pdfminer.converter import TextConverter
from pdfminer.layout import LAParams
from pdfminer.pdfpage import PDFPage
from cStringIO import StringIO


def document_to_text(filename):
    if filename[-5:] == ".docx":
        doc = docx.Document(filename)
        full_text = []
        for para in doc.paragraphs:
            full_text.append(para.text)
        global cv
        cv = '\n'.join(full_text)
        return cv
    elif filename[-4:] == ".pdf":
        return pdf_to_txt(filename)


def pdf_to_txt(file_path):
    rsrcmgr = PDFResourceManager()
    retstr = StringIO()
    codec = 'utf-8'
    laparams = LAParams()
    device = TextConverter(rsrcmgr, retstr, codec=codec, laparams=laparams)
    fp = file(file_path, 'rb')
    interpreter = PDFPageInterpreter(rsrcmgr, device)
    password = ""
    maxpages = 0
    caching = True
    pagenos = set()
    for page in PDFPage.get_pages(fp, pagenos, maxpages=maxpages, password=password, caching=caching,
                                  check_extractable=True):
        interpreter.process_page(page)
    fp.close()
    device.close()
    str = retstr.getvalue()
    retstr.close()
    global cv
    cv = str
    return cv
from convert_to_text import *

cv = 0

document_to_text("resources\CV.pdf")
print cv

您有一个需要解决的循环导入。这是脚本的执行路径:

  • main.py启动
  • main.py尝试从convert_to_text模块导入所有内容,触发convert_to_text.py的计算
  • convert_to_text.py尝试导入主模块,再次触发main.py的计算
  • 但此时main.py的计算在尝试导入convert_to_文本模块时停止,因此
    cv
    还不存在。当出现此错误时,解释器将退出并抛出NameError异常

    通常,您希望避免两个脚本相互导入。这称为循环导入。有很多方法可以让循环导入发挥作用,但它更多的时候是一个设计拙劣的程序的标志。我还没有看到一个循环导入的例子,它不能被重构成一个组织得更好的程序

    在这种情况下,两个模块都使用变量
    cv
    。您至少有两种可能的解决方案:

  • 修复函数调用结构以正确传递和返回参数。这段代码看起来并不需要在两个模块中引用
    cv
    。请参见布莱恩·奥克利的答案以获取示例。他在我面前指出了这一点

  • 如果对全局变量的使用存在不健康的附件,则可以重构代码,将
    cv
    移动到第三个模块中,main和convert_to_文本都可以导入,从而解决循环导入问题


  • 您有一个需要解决的循环导入。这是脚本的执行路径:

  • main.py启动
  • main.py尝试从convert_to_text模块导入所有内容,触发convert_to_text.py的计算
  • convert_to_text.py尝试导入主模块,再次触发main.py的计算
  • 但此时main.py的计算在尝试导入convert_to_文本模块时停止,因此
    cv
    还不存在。当出现此错误时,解释器将退出并抛出NameError异常

    通常,您希望避免两个脚本相互导入。这称为循环导入。有很多方法可以让循环导入发挥作用,但它更多的时候是一个设计拙劣的程序的标志。我还没有看到一个循环导入的例子,它不能被重构成一个组织得更好的程序

    在这种情况下,两个模块都使用变量
    cv
    。您至少有两种可能的解决方案:

  • 修复函数调用结构以正确传递和返回参数。这段代码看起来并不需要在两个模块中引用
    cv
    。请参见布莱恩·奥克利的答案以获取示例。他在我面前指出了这一点

  • 如果对全局变量的使用存在不健康的附件,则可以重构代码,将
    cv
    移动到第三个模块中,main和convert_to_文本都可以导入,从而解决循环导入问题


  • 如果您只需要从
    main.py
    中获得
    cv
    ,则只需将
    cv
    传递给需要它的函数即可。而且由于函数实际上不使用
    cv
    (除了设置它),因此也没有理由这样做

    只需删除导入的
    main
    ,并使用函数的返回值设置
    cv
    ,即可解决整个问题:

    cv = document_to_text("resources\CV.pdf")
    

    如果您只需要从
    main.py
    中获得
    cv
    ,则只需将
    cv
    传递给需要它的函数即可。而且由于函数实际上不使用
    cv
    (除了设置它),因此也没有理由这样做

    只需删除导入的
    main
    ,并使用函数的返回值设置
    cv
    ,即可解决整个问题:

    cv = document_to_text("resources\CV.pdf")
    

    可能是重复的,我想名字可能颠倒了。@AndréLaszlo-谢谢你的注意,我已经解决了这个问题。@methuselah阅读了你的回溯
    main->convert_to_text->main
    可能重复的名称,我认为名称可能会颠倒。@AndréLaszlo-感谢您的注意,我已经解决了这个问题。@methuselah阅读了您的回溯
    main->convert_to_text->main
    Haha,刚想点击“发布答案”,但你抢先一步。我们的答案结构完全相同,几乎一字不差。:)哈哈,我正要点击“发布你的答案”,但你抢先一步。我们的答案结构完全相同,几乎一字不差。:)是的,这是一个更好的答案。我没有仔细阅读代码。。。删除“全局”变量是一种方法。是的,这是一个更好的答案。我没有仔细阅读代码。。。删除“全局”变量是一条可行之路。