Python Pmw 和 cx_Freeze?

Posted

技术标签:

【中文标题】Python Pmw 和 cx_Freeze?【英文标题】:Python Pmw and cx_Freeze? 【发布时间】:2011-07-21 07:56:17 【问题描述】:

我无法从使用 Pmw(Python 大型小部件)的 python 程序中生成可执行文件。我使用 cx_Freeze(通过 gui 后端“Gui2Exe”)。搜索 Pmw 站点我发现这是由 Pmw 库在运行时检查模块的方式引起的,当您使用 py2exe 或类似程序时它不起作用,因为这些库位于 zip 文件中。更多信息可以在这里找到:http://pmw.sourceforge.net/doc/dynamicloader.html 因此,他们在该页面的“冻结 Pmw”下提供了一个解决方案,提供了一个脚本,该脚本生成一个可以轻松冻结的独立 Pmw 模块。但是,该脚本使用不推荐使用的代码,并且不适用于 Python 2.6 +。我试过修改它,但没有成功。

编辑:我想提一下,仅将 'regex' 替换为 're' 是行不通的。

#!/usr/bin/env python

# Helper script when freezing Pmw applications.  It concatenates all
# Pmw megawidget files into a single file, 'Pmw.py', in the current
# directory.  The script must be called with one argument, being the
# path to the 'lib' directory of the required version of Pmw.
# To freeze a Pmw application, you will also need to copy the
# following files to the application directory before freezing:
#
#    PmwBlt.py PmwColor.py

import os
import regsub
import string
import sys

# The order of these files is significant.  Files which reference
# other files must appear later.  Files may be deleted if they are not
# used.
files = [
    'Dialog', 'TimeFuncs', 'Balloon', 'ButtonBox', 'EntryField',
    'Group', 'LabeledWidget', 'MainMenuBar', 'MenuBar', 'MessageBar',
    'MessageDialog', 'NoteBook', 'OptionMenu', 'PanedWidget', 'PromptDialog',
    'Radioselect', 'ScrolledCanvas', 'ScrolledField', 'ScrolledFrame',
    'ScrolledListBox', 'ScrolledText', 'HistoryText', 'SelectionDialog',
    'TextDialog', 'TimeCounter', 'AboutDialog', 'ComboBox', 'ComboBoxDialog',
    'Counter', 'CounterDialog',
]

# Set this to 0 if you do not use any of the Pmw.Color functions:
needColor = 1

# Set this to 0 if you do not use any of the Pmw.Blt functions:
needBlt = 1

def expandLinks(path):
    if not os.path.isabs(path):
    path = os.path.join(os.getcwd(), path)
    while 1:
    if not os.path.islink(path):
        break
    dir = os.path.dirname(path)
    path = os.path.join(dir, os.readlink(path))

    return path

def mungeFile(file):
    # Read the file and modify it so that it can be bundled with the
    # other Pmw files.
    file = 'Pmw' + file + '.py'
    text = open(os.path.join(srcdir, file)).read()
    text = regsub.gsub('import Pmw\>', '', text)
    text = regsub.gsub('INITOPT = Pmw.INITOPT', '', text)
    text = regsub.gsub('\<Pmw\.', '', text)
    text = '\n' + ('#' * 70) + '\n' + '### File: ' + file + '\n' + text
    return text

# Work out which version is being bundled.
file = sys.argv[0]
file = os.path.normpath(file)
file = expandLinks(file)

dir = os.path.dirname(file)
dir = expandLinks(dir)
dir = os.path.dirname(dir)
dir = expandLinks(dir)
dir = os.path.basename(dir)

version = string.replace(dir[4:], '_', '.')

# Code to import the Color module.
colorCode = """
import PmwColor
Color = PmwColor
del PmwColor
"""

# Code to import the Blt module.
bltCode = """
import PmwBlt
Blt = PmwBlt
del PmwBlt
"""

# Code used when not linking with PmwBlt.py.
ignoreBltCode = """
_bltImported = 1
_bltbusyOK = 0
"""

# Code to define the functions normally supplied by the dynamic loader.
extraCode = """

### Loader functions:

_VERSION = '%s'

def setversion(version):
    if version != _VERSION:
        raise ValueError, 'Dynamic versioning not available'

def setalphaversions(*alpha_versions):
    if alpha_versions != ():
    raise ValueError, 'Dynamic versioning not available'

def version(alpha = 0):
    if alpha:
        return ()
    else:
        return _VERSION

def installedversions(alpha = 0):
    if alpha:
        return ()
    else:
        return (_VERSION,)

"""

if '-noblt' in sys.argv:
    sys.argv.remove('-noblt')
    needBlt = 0

if '-nocolor' in sys.argv:
    sys.argv.remove('-nocolor')
    needColor = 0

if len(sys.argv) != 2:
    print 'usage: bundlepmw.py [-noblt] [-nocolor] /path/to/Pmw/Pmw_X_X_X/lib'
    sys.exit()

srcdir = sys.argv[1]

if os.path.exists('Pmw.py'):
    print 'Pmw.py already exists. Remove it and try again.'
    sys.exit()

outfile = open('Pmw.py', 'w')

if needColor:
    outfile.write(colorCode)

if needBlt:
    outfile.write(bltCode)

outfile.write(extraCode % version)

# Specially handle PmwBase.py file:
text = mungeFile('Base')
text = regsub.gsub('import PmwLogicalFont', '', text)
text = regsub.gsub('PmwLogicalFont._font_initialise', '_font_initialise', text)
outfile.write(text)
if not needBlt:
    outfile.write(ignoreBltCode)

files.append('LogicalFont')
for file in files:
    text = mungeFile(file)
    outfile.write(text)

print ''
print '   Pmw.py has been created.'

if needColor or needBlt:
    print '   Before running freeze, also copy the following file(s):'
    if needBlt:
    print '   ' + os.path.join(srcdir, 'PmwBlt.py')
    if needColor:
    print '   ' + os.path.join(srcdir, 'PmwColor.py')

【问题讨论】:

【参考方案1】:

不幸的是,原始文件在制表符和空格方面存在一些问题(只需查看expandlinks 中的while 缩进即可)。

我修复了这些缩进问题,将 regsub.gsub 更改为 re.sub 并消除了 string 导入,使用字符串类型方法。

之后脚本完美运行:

   Pmw.py has been created.
   Before running freeze, also copy the following file(s):
   C:\Users\joaquin\Desktop\Pmw.1.3.2\src\Pmw\Pmw_1_3\lib\PmwBlt.py
   C:\Users\joaquin\Desktop\Pmw.1.3.2\src\Pmw\Pmw_1_3\lib\PmwColor.py

这里有更正的脚本:

#!/usr/bin/env python

# Helper script when freezing Pmw applications.  It concatenates all
# Pmw megawidget files into a single file, 'Pmw.py', in the current
# directory.  The script must be called with one argument, being the
# path to the 'lib' directory of the required version of Pmw.
# To freeze a Pmw application, you will also need to copy the
# following files to the application directory before freezing:
#
#    PmwBlt.py PmwColor.py

import os
import re
import sys

# The order of these files is significant.  Files which reference
# other files must appear later.  Files may be deleted if they are not
# used.
files = [
    'Dialog', 'TimeFuncs', 'Balloon', 'ButtonBox', 'EntryField',
    'Group', 'LabeledWidget', 'MainMenuBar', 'MenuBar', 'MessageBar',
    'MessageDialog', 'NoteBook', 'OptionMenu', 'PanedWidget', 'PromptDialog',
    'RadioSelect', 'ScrolledCanvas', 'ScrolledField', 'ScrolledFrame',
    'ScrolledListBox', 'ScrolledText', 'HistoryText', 'SelectionDialog',
    'TextDialog', 'TimeCounter', 'AboutDialog', 'ComboBox', 'ComboBoxDialog',
    'Counter', 'CounterDialog',
]

# Set this to 0 if you do not use any of the Pmw.Color functions:
needColor = 1

# Set this to 0 if you do not use any of the Pmw.Blt functions:
needBlt = 1

def expandLinks(path):
    if not os.path.isabs(path):
        path = os.path.join(os.getcwd(), path)
    while 1:
        if not os.path.islink(path):
            break
        dir = os.path.dirname(path)
        path = os.path.join(dir, os.readlink(path))

    return path

def mungeFile(file):
    # Read the file and modify it so that it can be bundled with the
    # other Pmw files.
    file = 'Pmw' + file + '.py'
    text = open(os.path.join(srcdir, file)).read()
    text = re.sub('import Pmw\>', '', text)
    text = re.sub('INITOPT = Pmw.INITOPT', '', text)
    text = re.sub('\<Pmw\.', '', text)
    text = '\n' + ('#' * 70) + '\n' + '### File: ' + file + '\n' + text
    return text

# Work out which version is being bundled.
file = sys.argv[0]
file = os.path.normpath(file)
file = expandLinks(file)

dir = os.path.dirname(file)
dir = expandLinks(dir)
dir = os.path.dirname(dir)
dir = expandLinks(dir)
dir = os.path.basename(dir)

version = dir[4:].replace('_', '.')

# Code to import the Color module.
colorCode = """
import PmwColor
Color = PmwColor
del PmwColor
"""
# Code to import the Blt module.
bltCode = """
import PmwBlt
Blt = PmwBlt
del PmwBlt
"""
# Code used when not linking with PmwBlt.py.
ignoreBltCode = """
_bltImported = 1
_bltbusyOK = 0
"""
# Code to define the functions normally supplied by the dynamic loader.
extraCode = """

### Loader functions:

_VERSION = '%s'

def setversion(version):
    if version != _VERSION:
        raise ValueError, 'Dynamic versioning not available'

def setalphaversions(*alpha_versions):
    if alpha_versions != ():
        raise ValueError, 'Dynamic versioning not available'

def version(alpha = 0):
    if alpha:
        return ()
    else:
        return _VERSION

def installedversions(alpha = 0):
    if alpha:
        return ()
    else:
        return (_VERSION,)

"""
if '-noblt' in sys.argv:
    sys.argv.remove('-noblt')
    needBlt = 0

if '-nocolor' in sys.argv:
    sys.argv.remove('-nocolor')
    needColor = 0

if len(sys.argv) != 2:
    print 'usage: bundlepmw.py [-noblt] [-nocolor] /path/to/Pmw/Pmw_X_X_X/lib'
    sys.exit()

srcdir = sys.argv[1]

if os.path.exists('Pmw.py'):
    print 'Pmw.py already exists. Remove it and try again.'
    sys.exit()

outfile = open('Pmw.py', 'w')

if needColor:
    outfile.write(colorCode)

if needBlt:
    outfile.write(bltCode)

outfile.write(extraCode % version)

# Specially handle PmwBase.py file:
text = mungeFile('Base')
text = re.sub('import PmwLogicalFont', '', text)
text = re.sub('PmwLogicalFont._font_initialise', '_font_initialise', text)
outfile.write(text)
if not needBlt:
    outfile.write(ignoreBltCode)

files.append('LogicalFont')
for file in files:
    text = mungeFile(file)
    outfile.write(text)

print ''
print '   Pmw.py has been created.'

if needColor or needBlt:
    print '   Before running freeze, also copy the following file(s):'
    if needBlt:
        print '   ' + os.path.join(srcdir, 'PmwBlt.py')
    if needColor:
        print '   ' + os.path.join(srcdir, 'PmwColor.py')

【讨论】:

太棒了。我现在就试试。我建议联系 Pmw 开发人员以添加更改。好吧,你做到了,这就是我说的原因,如果你没有时间,我可以为你做。 @Brock123,没必要。我检查了该站点,虽然它似乎是废弃软件,但贡献者 gruber 几个月前更新了脚本并将其放入 cvs sourceforge repository 你们能帮我解释一下吗,我不明白,我是初学者

以上是关于Python Pmw 和 cx_Freeze?的主要内容,如果未能解决你的问题,请参考以下文章

使用 Python 的 cx_Freeze 安装程序添加开始菜单快捷方式

cx_Freeze 错误模块 SSL 不可用 Python 3.7 Windows 10

Pmw大控件

ImportError:运行我的应用程序时没有名为“队列”的模块被 cx_freeze 冻结

使用 cx_freeze 将脚本转换为 .exe 时如何包含 tkinter?

使用 Pmw 时出现“ImportError:没有名为 tkinter 的模块”