【问题标题】:cx_Freeze: Python error in main script - ImportError: DLL Load Failedcx_Freeze:主脚本中的 Python 错误 - ImportError:DLL 加载失败
【发布时间】:2018-06-27 16:33:04
【问题描述】:

我正在构建一个小的 Python 3.6.5 工具,它接收一个 XML 文档并输出它的所有 XPath。它运作良好,但是我需要以 EXE 形式分发它。我是在Win10上运行的,只需要提供给Win10用户即可。

我的主要代码是;

from tkinter import filedialog
from tkinter import *
from pathlib import Path
import winsound
from lxml import etree
import csv

root = Tk()

root.geometry("250x200")
root.resizable(0, 0)


class gui:
    def __init__(self, master):
        self.master = master
        master.title("XGen")

        self.welcome = Label(master, text="Welcome to")
        self.welcome.config(font=("Arial", 10))
        self.welcome.pack()

        self.header = Label(master, text="The XPath Generator")
        self.header.config(font=("Arial", 16))
        self.header.pack()

        self.description = Label(master, text="This Tool Takes in an XML Document\nand Provides all its XPaths")
        self.description.config(font=("Arial", 10))
        self.description.pack()

        self.greet_button = Button(master, text="Select Input XML", command=self.greet)
        self.greet_button.pack()

        self.reportFilename = Label(master, text="")
        self.reportFilename.pack()

        self.reportProgress = Label(master, text="")
        self.reportProgress.pack()

        # self.close_button = Button(master, text="Close", command=master.quit)
        # self.close_button.pack()

    def greet(self):
        print("File Selection Started")

        from_file_path = filedialog.askopenfilename(initialdir="/",
                                                    title="Select file",
                                                    filetypes=(("XML Files", "*.xml"), ("all files", "*.*")))

        from_file_path_split = Path(from_file_path).parts
        to_file_path = ''

        if from_file_path is '':
            self.reportFilename.config(text="You Did not Select a File")
            print("No File Selected. File Selection Ended")

        else:
            self.reportFilename.config(text="You Selected " + from_file_path_split[-1])
            print("From File Path = " + from_file_path)
            print("File Name = " + from_file_path_split[-1])
            to_file_path = filedialog.asksaveasfilename(initialdir=from_file_path,
                                                        title="Save As",
                                                        filetypes=(("CSV Files", "*.csv"), ("all files", "*.*")))

        if to_file_path is '' or to_file_path == 'Null':
            self.reportProgress.config(text="Please select a Save Location")
        # elif to_file_split[-1][:4] == "xsd":
        else:
            to_file_split = Path(to_file_path).parts
            to_file_name = to_file_split[-1]
            print("Filename = " + to_file_name)

            to_file_extension = to_file_split[-1][-4:]
            print("Last 4 chars = " + to_file_extension)

            if to_file_extension == ".csv":
                pass
            else:
                to_file_path = to_file_path + ".csv"
                # to_file_name = to_file_path
                print("To File Path = " + to_file_path)

            if from_file_path == '' or to_file_path == '' or to_file_path == 'Null':

                self.reportProgress.config(text="Please Select a Valid XML File")
                winsound.PlaySound("SystemExclamation", winsound.SND_ALIAS)
                print("Bad File, Try Again")

            else:
                out(from_file_path, to_file_path)

                self.reportProgress.config(text="Generated " + Path(to_file_path).parts[-1])
                print("XGen Complete")


def out(in_path, out_path):
    with open(in_path, 'r') as source_file:
        xml = source_file.read()

    root = etree.fromstring(xml)

    tree = etree.ElementTree(root)

    line = ['XPath', 'Attribute Name', 'Current Data']

    if out_path is None:
        return 1
    else:
        pass

    with open(out_path, 'w', newline='') as csv_file:
        csv_writer = csv.writer(csv_file, delimiter=',', quotechar='"', quoting=csv.QUOTE_ALL)
        csv_writer.writerow(line)
        for e in root.iter():
            path = tree.getpath(e)
            list_of_attributes = []
            nodes = root.xpath(path)
            for node in nodes:
                attrs = []
                for att in node.attrib:
                    attrs.append(("@" + att, node.attrib[att]))
                list_of_attributes.append(attrs)
                for attributes in list_of_attributes:
                    line = [path, None]
                    csv_writer.writerow(line)
                    if len(attributes) == 0:
                        pass
                    else:
                        for x in range(len(attributes)):
                            xpath = path + attributes[x][0]
                            current_data = (attributes[x][1])
                            attribute_name = attributes[x][0]
                            line = [xpath, attribute_name, current_data]
                            csv_writer.writerow(line)


my_gui = gui(root)
root.mainloop()

(请原谅乱码!我确实打算为下一个版本清理它!)

setup.py 包含以下内容;

import sys
from cx_Freeze import setup, Executable

base = None
if sys.platform == 'win32':
    base = 'Win32GUI'

executables = [
    Executable('xin.py', base=base)
]

setup(name='XGen',
      version='0.1',
      description='XGen',
      executables=executables
      )

这确实允许程序构建一个 EXE,但是当该 EXE 运行时,它会返回此错误。

我一直在到处寻找解决方案。

  • 我发现了一个建议,即卸载所有版本的 Python,然后只安装一个版本可能会奏效,但并不令人愉快。
  • 我之前尝试过 Py2exe,但也没有用。
  • 我发现另一个建议是 PATH 可能不正确,所以检查了一下,那里的一切似乎也正确。

按照错误文本的建议,我还尝试检查 tkinter 是否已正确安装。这个程序不仅可以通过Python运行,而且IDLE让我import tkinter

什么可能导致 cx_Freeze 抛出此错误?

谢谢!

【问题讨论】:

    标签: python python-3.x cx-freeze


    【解决方案1】:

    location of the TK DLLs 需要添加到setup.py。在 Windows 10 上,这可能位于 C: 或 C:\Users\[username]\AppData\Local\Programs\Python\Python36-32/DLLs 的根目录中。添加一个变量来存储该路径,然后将其设为 raw string 并带有前导 r

    import os
    import sys
    from cx_Freeze import setup, Executable
    
    
    PYTHON_INSTALL_DIR = os.path.dirname(os.path.dirname(os.__file__))
    os.environ['TCL_LIBRARY'] = os.path.join(PYTHON_INSTALL_DIR, 'tcl', 'tcl8.6')
    os.environ['TK_LIBRARY'] = os.path.join(PYTHON_INSTALL_DIR, 'tcl', 'tk8.6')
    
    
    base = None
    if sys.platform == 'win32':
        base = 'Win32GUI'
    
    syspath = r"C:\Users\[username]\AppData\Local\Programs\Python\Python36-32/DLLs"
    
    buildOptions = dict(
        packages=[],
        excludes=[],
        include_files=[syspath + '/tcl86t.dll', syspath + '/tk86t.dll']
    )
    
    executables = [
        Executable('xin.py', base=base)
    ]
    
    setup(name='XGen',
          version='0.1',
          options=dict(build_exe=buildOptions),
          description='XGen',
          executables=executables
          )
    

    非常感谢 MrLeeh 和 DeePak M. Birajdar!

    【讨论】:

    • 仍然给了我完全相同的错误。我已经在不同的桌面上运行它。它在我自己的机器上运行良好。我已经包含了所有必需的 DLL 文件。
    • 你试过在容器中构建它吗?这将确保包含任何依赖项。
    【解决方案2】:

    我遇到了同样的问题,但结果是我错过了一些要包含在最终构建中的文件夹。 例如,我的代码在初始化级别从文件夹(名为“DataBase”)读取一些 JSON 文件,但我没有在构建中包含该文件夹。 这是我的代码:

    import sys
    
    from cx_Freeze import setup, Executable
    base = None
    
    application_title = 'Myapp'
    main_python_file = 'main.py'
    
    
    if sys.platform == 'win32':
        base = 'Win32GUI'
    
    includes = []
    include_files = ['DataBase']
    
    setup(name=application_title, version='1',
          options={'build_exe': {'includes': includes, 'include_files': include_files}},
          executables=[Executable(main_python_file, base=base)])
    

    【讨论】:

      猜你喜欢
      • 2016-10-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-04-03
      • 1970-01-01
      • 2016-07-13
      相关资源
      最近更新 更多