编译.pyw文件使其像.pyc文件一样无控制台运行
我想把一个.pyw文件编译成.pyc文件,但不想让它在控制台中运行。当我直接编译这个文件时,结果是一个.pywc文件,但看起来pythonw.exe并没有把这个扩展名当作它的文件类型,就像python.exe对待.pyc文件那样。
结果就是,当你尝试直接双击这个文件时,它没有任何反应,或者如果你把扩展名改成.pyc,就会出现控制台窗口。
有没有人知道怎么解决这个问题?有没有办法让.pyc文件在没有控制台的情况下运行?
谢谢!
更新:
因为通过execfile运行或者在Windows中双击图标并不能生成这个文件的编译版本,所以我在命令行中启动Python,然后:
import py_compile
py_compile.compile("[FileName].pyw")
这就是我得到.pywc扩展名的原因。我的Python版本是2.5.4。
4 个回答
你可以使用FTYPE和ASSOC这两个命令,把.pywc文件和pythonw.exe程序关联起来。
ASSOC命令是用来把文件扩展名和文件类型连接起来的,而FTYPE命令则是把文件类型和打开它所用的命令连接起来。下面的命令展示了我电脑上已有的关联情况:
C:\Python26>assoc .py
.py=Python.File
C:\Python26>assoc .pyc
.pyc=Python.CompiledFile
C:\Python26>assoc .pyw
.pyw=Python.NoConFile
C:\Python26>assoc .pywc
File association not found for extension .pywc
这些命令显示了每个扩展名是和哪个程序通过文件类型关联的:
C:\Python26>ftype Python.CompiledFile
Python.CompiledFile="C:\Python26\python.exe" "%1" %*
C:\Python26>ftype Python.NoConFile
Python.NoConFile="C:\Python26\pythonw.exe" "%1" %*
所以看起来你可以这样把.pywc文件关联到Python.NoConFile:
assoc .pywc=Python.NoConFile
读取 .pyw
文件的解释器也可以读取编译过的 .pyc
格式的文件。你只需要把 .pyc
文件的名字改成 .pyw
就可以了。这样它就能运行了(不过还是要注意版本的问题),而且你不会看到那个难看的控制台窗口。
(接着OP帖子中的一些讨论)
如果你需要给客户或用户提供编译好的应用程序,格式是*.pyc或*.pyo,并且希望在执行时不打开控制台,一个不错的选择是留一个*.pyw的包装文件来调用主应用程序。
假设主应用程序在main.pyc
中,入口点是main
,我们把包装文件叫做top.pyw
,它通常看起来像这样:
# top.pyw file
import main
if __name__ == "__main__":
import sys
main.main(*sys.argv[1:])
你的main.py文件看起来会是这样的:
# main.py file
"""
Main module documentation (optional)
"""
# import modules
# function and class definitions
def main(*argv):
# Parses the options (optional)
import optparse
parser = optparse.OptionParser(usage="%prog [<options>]\n" + __doc__)
parser.add_option(...)
parser.add_option(...)
opt, args = parser.parse_args(list(argv))
# Calls the appropriate function:
my_function(...)
另外要注意,*.pyc文件通常是特定版本的。你可以检查一下上面的解决方案是否与pyInstaller和类似的“独立”分发方法兼容。
编辑 => 事实上,如果你使用pyInstaller,你可以简单地把所有脚本包含进去,生成一个独立于Python安装的可执行文件,并且启动时不会有控制台(在创建规格时使用-w
选项)。你甚至不需要使用包装文件或更改扩展名。虽然文件会大一些,但这可能正是你想要的。
最后,万一你想要的是这个:如果你不希望别人从编译后的字节码中提取源代码,别忘了你需要额外的保护措施。这被称为代码混淆,在SO上还有其他相关的讨论(比如这个)。如果你在这个问题上只找到旧的答案,不要犹豫,发个新问题,因为这些事情变化得很快。