如何使用pyinstaller打包源代码,pyinstaller打包命令
这篇文章主要介绍了关于Pyinstaller打包鳗和简介及安装需要注意的坑,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
这几天我们团队用大蟒做了一个游戏,引擎用的pygame,UI界面用的鳗鱼(一个大蟒库,用于利用超文本标记语言开发桌面应用程序,主要是因为夸脱机制太过复杂,而博主《死侍》不愿做费力不讨好的事,导入一个鳗鱼,便可通过HTML、CSS、JS开发桌面应用程序,这简直不要太爽,另外,关于鳗的使用也许我会在后续文章中写到)
1、打开cmd / Visual Studio等等可以装包的工具下载pyinstaller
如果是大蟒环境,那么:pip安装pyinstaller如果是城市环境,那么:康达安装pyinstaller
2、找到你的python_main程序
假设项目根目录为F:\xx\xx\xx,该目录的文件管理如下:
-网络(包括HTML、CSS、JS)
-游戏资源文件夹(包括图片巴拉巴拉的)
- Class1.py (Class1中导入第3类)
- Class2.py
- Class3.py
- Python_Main.py (Python_Main中导入一类,二类和鳗鱼)
3、查看eel库
鳗库一般在现场包装里
打开__main__ .巴拉圭文件
#鳗鱼的__main__ .巴拉圭文件
从__未来_ _导入打印_功能
导入系统
将pkg _资源作为包装导入
导入PyInstaller .__main__ as pyi
导入操作系统
args=sys.argv[1:]
main_script=args.pop(0)
web_folder=args.pop(0)
打印(使用主脚本" %s "和网文件夹" %s "构建可执行文件.\n %
(主脚本,web文件夹))
eel _ js _ file=pkg。资源文件名( eel , eel.js )
js _ file _ arg= % s % seel %(eel _ js _ file,os.pathsep)
web_folder _ arg= % s % s % s %(web _ folder,os.pathsep,web _ folder)
needed_args=[ - hidden-import , bottle_websocket ,
- add-data ,js_file_arg ,- add-data ,web_folder_arg]
full _ args=[main _ script]needed _ args args
打印(运行: \ npyinstaller , ).join(full_args), \n )
pyi.run(full_args)
注意到打印(“使用主脚本" %s "和网文件夹" %s "构建可执行文件…\n" %
(主脚本,web文件夹))和打印(运行: \ npyinstaller , ).join(full_args), \n )可以知道鳗的打包原理还是利用pyinstaller
4、打开cmd开始将含有eel的python_main打包起来
Python-m eel f : \ xx \ xx \ xx \ Python _ main。py f : \ xx \ xx \ xx \ Web
这里暂时不加-w -f -i参数。(因为无论如何必然会出错)报错,提示找不到eel.js文件。呼呼,我就奇怪了,eel.js文件不就在那儿摆着吗。打开鳗的__init__ .巴拉圭文件查看
从_ _ future _ _ import print _ function # Python 2兼容的东西
从
builtins import range
from io import open
import gevent as gvt
import json as jsn
import bottle as btl
import bottle.ext.websocket as wbs
import re as rgx
import os
import eel.browsers as brw
import random as rnd
import sys
import pkg_resources as pkg
import socket
_eel_js_file = pkg.resource_filename(eel, eel.js)
_eel_js = open(_eel_js_file, encoding=utf-8).read()
_websockets = []
_call_return_values = {}
_call_return_callbacks = {}
_call_number = 0
_exposed_functions = {}
_js_functions = []
_mock_queue = []
_mock_queue_done = set()
# All start() options must provide a default value and explanation here
_start_args = {
mode: chrome, # What browser is used
host: localhost, # Hostname use for Bottle server
port: 8000, # Port used for Bottle server (use 0 for auto)
block: True, # Whether start() blocks calling thread
jinja_templates: None, # Folder for jinja2 templates
cmdline_args: [--disable-http-cache], # Extra cmdline flags to pass to browser start
size: None, # (width, height) of main window
position: None, # (left, top) of main window
geometry: {}, # Dictionary of size/position for all windows
close_callback: None, # Callback for when all windows have closed
app_mode: True, # (Chrome specific option)
all_interfaces: False, # Allow bottle server to listen for connections on all interfaces
disable_cache: True, # Sets the no-store response header when serving assets
app: btl.default_app(), # Allows passing in a custom Bottle instance, e.g. with middleware
}
# == Temporary (suppressable) error message to inform users of breaking API change for v1.0.0 ===
_start_args[suppress_error] = False
api_error_message =
----------------------------------------------------------------------------------
options argument deprecated in v1.0.0, see https://github.com/ChrisKnott/Eel
To suppress this error, add suppress_error=True to start() call.
This option will be removed in future versions
----------------------------------------------------------------------------------
# ===============================================================================================
# Public functions
def expose(name_or_function=None):
# Deal with @eel.expose() - treat as @eel.expose
if name_or_function is None:
return expose
if type(name_or_function) == str: # Called as @eel.expose("my_name")
name = name_or_function
def decorator(function):
_expose(name, function)
return function
return decorator
else:
function = name_or_function
_expose(function.__name__, function)
return function
def init(path, allowed_extensions=[.js, .html, .txt, .htm,
.xhtml, .vue]):
global root_path, _js_functions
root_path = _get_real_path(path)
js_functions = set()
for root, _, files in os.walk(root_path):
for name in files:
if not any(name.endswith(ext) for ext in allowed_extensions):
continue
try:
with open(os.path.join(root, name), encoding=utf-8) as file:
contents = file.read()
expose_calls = set()
finder = rgx.findall(reel\.expose\(([^\)]+)\), contents)
for expose_call in finder:
# If name specified in 2nd argument, strip quotes and store as function name
if , in expose_call:
expose_call = rgx.sub(r["\], , expose_call.split(,)[1])
expose_call = expose_call.strip()
# Verify that function name is valid
msg = "eel.expose() call contains ( or ="
assert rgx.findall(r[\(=], expose_call) == [], msg
expose_calls.add(expose_call)
js_functions.update(expose_calls)
except UnicodeDecodeError:
pass # Malformed file probably
_js_functions = list(js_functions)
for js_function in _js_functions:
_mock_js_function(js_function)
def start(*start_urls, **kwargs):
_start_args.update(kwargs)
if options in kwargs:
if _start_args[suppress_error]:
_start_args.update(kwargs[options])
else:
raise RuntimeError(api_error_message)
if _start_args[port] == 0:
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.bind((localhost, 0))
_start_args[port] = sock.getsockname()[1]
sock.close()
if _start_args[jinja_templates] != None:
from jinja2 import Environment, FileSystemLoader, select_autoescape
templates_path = os.path.join(root_path, _start_args[jinja_templates])
_start_args[jinja_env] = Environment(loader=FileSystemLoader(templates_path),
autoescape=select_autoescape([html, xml]))
# Launch the browser to the starting URLs
show(*start_urls)
def run_lambda():
if _start_args[all_interfaces] == True:
HOST = 0.0.0.0
else:
HOST = _start_args[host]
app = _start_args[app] # type: btl.Bottle
for route_path, route_params in BOTTLE_ROUTES.items():
route_func, route_kwargs = route_params
app.route(path=route_path, callback=route_func, **route_kwargs)
return btl.run(
host=HOST,
port=_start_args[port],
server=wbs.GeventWebSocketServer,
quiet=True,
app=app)
# Start the webserver
if _start_args[block]:
run_lambda()
else:
spawn(run_lambda)
def show(*start_urls):
brw.open(start_urls, _start_args)
def sleep(seconds):
gvt.sleep(seconds)
def spawn(function, *args, **kwargs):
gvt.spawn(function, *args, **kwargs)
# Bottle Routes
def _eel():
start_geometry = {default: {size: _start_args[size],
position: _start_args[position]},
pages: _start_args[geometry]}
page = _eel_js.replace(/** _py_functions **/,
_py_functions: %s, % list(_exposed_functions.keys()))
page = page.replace(/** _start_geometry **/,
_start_geometry: %s, % _safe_json(start_geometry))
btl.response.content_type = application/javascript
_set_response_headers(btl.response)
return page
def _static(path):
response = None
if jinja_env in _start_args and jinja_templates in _start_args:
template_prefix = _start_args[jinja_templates] + /
if path.startswith(template_prefix):
n = len(template_prefix)
template = _start_args[jinja_env].get_template(path[n:])
response = btl.HTTPResponse(template.render())
if response is None:
response = btl.static_file(path, root=root_path)
_set_response_headers(response)
return response
def _websocket(ws):
global _websockets
for js_function in _js_functions:
_import_js_function(js_function)
page = btl.request.query.page
if page not in _mock_queue_done:
for call in _mock_queue:
_repeated_send(ws, _safe_json(call))
_mock_queue_done.add(page)
_websockets += [(page, ws)]
while True:
msg = ws.receive()
if msg is not None:
message = jsn.loads(msg)
spawn(_process_message, message, ws)
else:
_websockets.remove((page, ws))
break
_websocket_close(page)
BOTTLE_ROUTES = {
"/eel.js": (_eel, dict()),
"/<path:path>": (_static, dict()),
"/eel": (_websocket, dict(apply=[wbs.websocket]))
}
# Private functions
def _safe_json(obj):
return jsn.dumps(obj, default=lambda o: None)
def _repeated_send(ws, msg):
for attempt in range(100):
try:
ws.send(msg)
break
except Exception:
sleep(0.001)
def _process_message(message, ws):
if call in message:
return_val = _exposed_functions[message[name]](*message[args])
_repeated_send(ws, _safe_json({ return: message[call],
value: return_val }))
elif return in message:
call_id = message[return]
if call_id in _call_return_callbacks:
callback = _call_return_callbacks.pop(call_id)
callback(message[value])
else:
_call_return_values[call_id] = message[value]
else:
print(Invalid message received: , message)
def _get_real_path(path):
if getattr(sys, frozen, False):
return os.path.join(sys._MEIPASS, path)
else:
return os.path.abspath(path)
def _mock_js_function(f):
exec(%s = lambda *args: _mock_call("%s", args) % (f, f), globals())
def _import_js_function(f):
exec(%s = lambda *args: _js_call("%s", args) % (f, f), globals())
def _call_object(name, args):
global _call_number
_call_number += 1
call_id = _call_number + rnd.random()
return {call: call_id, name: name, args: args}
def _mock_call(name, args):
call_object = _call_object(name, args)
global _mock_queue
_mock_queue += [call_object]
return _call_return(call_object)
def _js_call(name, args):
call_object = _call_object(name, args)
for _, ws in _websockets:
_repeated_send(ws, _safe_json(call_object))
return _call_return(call_object)
def _call_return(call):
call_id = call[call]
def return_func(callback=None):
if callback is not None:
_call_return_callbacks[call_id] = callback
else:
for w in range(10000):
if call_id in _call_return_values:
return _call_return_values.pop(call_id)
sleep(0.001)
return return_func
def _expose(name, function):
msg = Already exposed function with name "%s" % name
assert name not in _exposed_functions, msg
_exposed_functions[name] = function
def _websocket_close(page):
close_callback = _start_args.get(close_callback)
if close_callback is not None:
sockets = [p for _, p in _websockets]
close_callback(page, sockets)
else:
# Default behaviour - wait 1s, then quit if all sockets are closed
sleep(1.0)
if len(_websockets) == 0:
sys.exit()
def _set_response_headers(response):
if _start_args[disable_cache]:
# https://stackoverflow.com/a/24748094/280852
response.set_header(Cache-Control, no-store)
注意到了吗?代码中有这样两句:
_eel_js_file = pkg.resource_filename(eel, eel.js)_eel_js = open(_eel_js_file, encoding=utf-8).read()
一不做,二不休,把eel.js的内容复制下来,然后,奥里给。将代码做如下修改(即贴即用)
from __future__ import print_function # Python 2 compatibility stufffrom builtins import range
from io import open
import gevent as gvt
import json as jsn
import bottle as btl
import bottle.ext.websocket as wbs
import re as rgx
import os
import eel.browsers as brw
import random as rnd
import sys
import pkg_resources as pkg
import socket
eelJS =
eel = {
_host: window.location.origin,
set_host: function (hostname) {
eel._host = hostname
},
expose: function(f, name) {
if(name === undefined){
name = f.toString();
let i = function .length, j = name.indexOf(();
name = name.substring(i, j).trim();
}
eel._exposed_functions[name] = f;
},
guid: function() {
return eel._guid;
},
// These get dynamically added by library when file is served
/** _py_functions **/
/** _start_geometry **/
_guid: ([1e7]+-1e3+-4e3+-8e3+-1e11).replace(/[018]/g, c =>
(c ^ crypto.getRandomValues(new Uint8Array(1))[0] & 15 >> c / 4).toString(16)
),
_exposed_functions: {},
_mock_queue: [],
_mock_py_functions: function() {
for(let i = 0; i < eel._py_functions.length; i++) {
let name = eel._py_functions[i];
eel[name] = function() {
let call_object = eel._call_object(name, arguments);
eel._mock_queue.push(call_object);
return eel._call_return(call_object);
}
}
},
_import_py_function: function(name) {
let func_name = name;
eel[name] = function() {
let call_object = eel._call_object(func_name, arguments);
eel._websocket.send(eel._toJSON(call_object));
return eel._call_return(call_object);
}
},
_call_number: 0,
_call_return_callbacks: {},
_call_object: function(name, args) {
let arg_array = [];
for(let i = 0; i < args.length; i++){
arg_array.push(args[i]);
}
let call_id = (eel._call_number += 1) + Math.random();
return {call: call_id, name: name, args: arg_array};
},
_sleep: function(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
},
_toJSON: function(obj) {
return JSON.stringify(obj, (k, v) => v === undefined ? null : v);
},
_call_return: function(call) {
return function(callback = null) {
if(callback != null) {
eel._call_return_callbacks[call.call] = callback;
} else {
return new Promise(function(resolve) {
eel._call_return_callbacks[call.call] = resolve;
});
}
}
},
_position_window: function(page) {
let size = eel._start_geometry【default】.size;
let position = eel._start_geometry[default].position;
if(page in eel._start_geometry.pages) {
size = eel._start_geometry.pages【page】.size;
position = eel._start_geometry.pages【page】.position;
}
if(size != null){
window.resizeTo(size[0], size[1]);
}
if(position != null){
window.moveTo(position[0], position[1]);
}
},
_init: function() {
eel._mock_py_functions();
document.addEventListener("DOMContentLoaded", function(event) {
let page = window.location.pathname.substring(1);
eel._position_window(page);
let websocket_addr = (eel._host + /eel).replace(http, ws);
websocket_addr += (?page= + page);
eel._websocket = new WebSocket(websocket_addr);
eel._websocket.onopen = function() {
for(let i = 0; i < eel._py_functions.length; i++){
let py_function = eel._py_functions[i];
eel._import_py_function(py_function);
}
while(eel._mock_queue.length > 0) {
let call = eel._mock_queue.shift();
eel._websocket.send(eel._toJSON(call));
}
};
eel._websocket.onmessage = function (e) {
let message = JSON.parse(e.data);
if(message.hasOwnProperty(call) ) {
// Python making a function call into us
if(message.name in eel._exposed_functions) {
let return_val = eel._exposed_functions[message.name](...message.args);
eel._websocket.send(eel._toJSON({return: message.call, value: return_val}));
}
} else if(message.hasOwnProperty(return)) {
// Python returning a value to us
if(message[return] in eel._call_return_callbacks) {
eel._call_return_callbacks[message[return]](message.value);
}
} else {
throw Invalid message + message;
}
};
});
}
}
eel._init();
if(typeof require !== undefined){
// Avoid name collisions when using Electron, so jQuery etc work normally
window.nodeRequire = require;
delete window.require;
delete window.exports;
delete window.module;
}
try:
_eel_js_file = pkg.resource_filename(eel, eel.js)
_eel_js = open(_eel_js_file, encoding=utf-8).read()
except:
_eel_js = eelJS
_websockets = []
_call_return_values = {}
_call_return_callbacks = {}
_call_number = 0
_exposed_functions = {}
_js_functions = []
_mock_queue = []
_mock_queue_done = set()
# All start() options must provide a default value and explanation here
_start_args = {
mode: chrome, # What browser is used
host: localhost, # Hostname use for Bottle server
port: 8000, # Port used for Bottle server (use 0 for auto)
block: True, # Whether start() blocks calling thread
jinja_templates: None, # Folder for jinja2 templates
cmdline_args: [--disable-http-cache], # Extra cmdline flags to pass to browser start
size: None, # (width, height) of main window
position: None, # (left, top) of main window
geometry: {}, # Dictionary of size/position for all windows
close_callback: None, # Callback for when all windows have closed
app_mode: True, # (Chrome specific option)
all_interfaces: False, # Allow bottle server to listen for connections on all interfaces
disable_cache: True, # Sets the no-store response header when serving assets
app: btl.default_app(), # Allows passing in a custom Bottle instance, e.g. with middleware
}
# == Temporary (suppressable) error message to inform users of breaking API change for v1.0.0 ===
_start_args[suppress_error] = False
api_error_message =
----------------------------------------------------------------------------------
options argument deprecated in v1.0.0, see https://github.com/ChrisKnott/Eel
To suppress this error, add suppress_error=True to start() call.
This option will be removed in future versions
----------------------------------------------------------------------------------
# ===============================================================================================
# Public functions
def expose(name_or_function=None):
# Deal with @eel.expose() - treat as @eel.expose
if name_or_function is None:
return expose
if type(name_or_function) == str: # Called as @eel.expose("my_name")
name = name_or_function
def decorator(function):
_expose(name, function)
return function
return decorator
else:
function = name_or_function
_expose(function.__name__, function)
return function
def init(path, allowed_extensions=[.js, .html, .txt, .htm,
.xhtml, .vue]):
global root_path, _js_functions
root_path = _get_real_path(path)
js_functions = set()
for root, _, files in os.walk(root_path):
for name in files:
if not any(name.endswith(ext) for ext in allowed_extensions):
continue
try:
with open(os.path.join(root, name), encoding=utf-8) as file:
contents = file.read()
expose_calls = set()
finder = rgx.findall(reel\.expose\(([^\)]+)\), contents)
for expose_call in finder:
# If name specified in 2nd argument, strip quotes and store as function name
if , in expose_call:
expose_call = rgx.sub(r["\], , expose_call.split(,)[1])
expose_call = expose_call.strip()
# Verify that function name is valid
msg = "eel.expose() call contains ( or ="
assert rgx.findall(r[\(=], expose_call) == [], msg
expose_calls.add(expose_call)
js_functions.update(expose_calls)
except UnicodeDecodeError:
pass # Malformed file probably
_js_functions = list(js_functions)
for js_function in _js_functions:
_mock_js_function(js_function)
def start(*start_urls, **kwargs):
_start_args.update(kwargs)
if options in kwargs:
if _start_args[suppress_error]:
_start_args.update(kwargs[options])
else:
raise RuntimeError(api_error_message)
if _start_args[port] == 0:
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.bind((localhost, 0))
_start_args[port] = sock.getsockname()[1]
sock.close()
if _start_args[jinja_templates] != None:
from jinja2 import Environment, FileSystemLoader, select_autoescape
templates_path = os.path.join(root_path, _start_args[jinja_templates])
_start_args[jinja_env] = Environment(loader=FileSystemLoader(templates_path),
autoescape=select_autoescape([html, xml]))
# Launch the browser to the starting URLs
show(*start_urls)
def run_lambda():
if _start_args[all_interfaces] == True:
HOST = 0.0.0.0
else:
HOST = _start_args[host]
app = _start_args[app] # type: btl.Bottle
for route_path, route_params in BOTTLE_ROUTES.items():
route_func, route_kwargs = route_params
app.route(path=route_path, callback=route_func, **route_kwargs)
return btl.run(
host=HOST,
port=_start_args[port],
server=wbs.GeventWebSocketServer,
quiet=True,
app=app)
# Start the webserver
if _start_args[block]:
run_lambda()
else:
spawn(run_lambda)
def show(*start_urls):
brw.open(start_urls, _start_args)
def sleep(seconds):
gvt.sleep(seconds)
def spawn(function, *args, **kwargs):
gvt.spawn(function, *args, **kwargs)
# Bottle Routes
def _eel():
start_geometry = {default: {size: _start_args[size],
position: _start_args[position]},
pages: _start_args[geometry]}
page = _eel_js.replace(/** _py_functions **/,
_py_functions: %s, % list(_exposed_functions.keys()))
page = page.replace(/** _start_geometry **/,
_start_geometry: %s, % _safe_json(start_geometry))
btl.response.content_type = application/javascript
_set_response_headers(btl.response)
return page
def _static(path):
response = None
if jinja_env in _start_args and jinja_templates in _start_args:
template_prefix = _start_args[jinja_templates] + /
if path.startswith(template_prefix):
n = len(template_prefix)
template = _start_args[jinja_env].get_template(path[n:])
response = btl.HTTPResponse(template.render())
if response is None:
response = btl.static_file(path, root=root_path)
_set_response_headers(response)
return response
def _websocket(ws):
global _websockets
for js_function in _js_functions:
_import_js_function(js_function)
page = btl.request.query.page
if page not in _mock_queue_done:
for call in _mock_queue:
_repeated_send(ws, _safe_json(call))
_mock_queue_done.add(page)
_websockets += [(page, ws)]
while True:
msg = ws.receive()
if msg is not None:
message = jsn.loads(msg)
spawn(_process_message, message, ws)
else:
_websockets.remove((page, ws))
break
_websocket_close(page)
BOTTLE_ROUTES = {
"/eel.js": (_eel, dict()),
"/<path:path>": (_static, dict()),
"/eel": (_websocket, dict(apply=[wbs.websocket]))
}
# Private functions
def _safe_json(obj):
return jsn.dumps(obj, default=lambda o: None)
def _repeated_send(ws, msg):
for attempt in range(100):
try:
ws.send(msg)
break
except Exception:
sleep(0.001)
def _process_message(message, ws):
if call in message:
return_val = _exposed_functions[message[name]](*message[args])
_repeated_send(ws, _safe_json({ return: message[call],
value: return_val }))
elif return in message:
call_id = message[return]
if call_id in _call_return_callbacks:
callback = _call_return_callbacks.pop(call_id)
callback(message[value])
else:
_call_return_values[call_id] = message[value]
else:
print(Invalid message received: , message)
def _get_real_path(path):
if getattr(sys, frozen, False):
return os.path.join(sys._MEIPASS, path)
else:
return os.path.abspath(path)
def _mock_js_function(f):
exec(%s = lambda *args: _mock_call("%s", args) % (f, f), globals())
def _import_js_function(f):
exec(%s = lambda *args: _js_call("%s", args) % (f, f), globals())
def _call_object(name, args):
global _call_number
_call_number += 1
call_id = _call_number + rnd.random()
return {call: call_id, name: name, args: args}
def _mock_call(name, args):
call_object = _call_object(name, args)
global _mock_queue
_mock_queue += [call_object]
return _call_return(call_object)
def _js_call(name, args):
call_object = _call_object(name, args)
for _, ws in _websockets:
_repeated_send(ws, _safe_json(call_object))
return _call_return(call_object)
def _call_return(call):
call_id = call[call]
def return_func(callback=None):
if callback is not None:
_call_return_callbacks[call_id] = callback
else:
for w in range(10000):
if call_id in _call_return_values:
return _call_return_values.pop(call_id)
sleep(0.001)
return return_func
def _expose(name, function):
msg = Already exposed function with name "%s" % name
assert name not in _exposed_functions, msg
_exposed_functions[name] = function
def _websocket_close(page):
close_callback = _start_args.get(close_callback)
if close_callback is not None:
sockets = [p for _, p in _websockets]
close_callback(page, sockets)
else:
# Default behaviour - wait 1s, then quit if all sockets are closed
sleep(1.0)
if len(_websockets) == 0:
sys.exit()
def _set_response_headers(response):
if _start_args[disable_cache]:
# https://stackoverflow.com/a/24748094/280852
response.set_header(Cache-Control, no-store)
ok,下面在运行一次cmd,执行之前的代码,不报错了。但是,这次又遇到了新的问题。
utf-8 codec cant decode byte 0xce
woc。这编码怎么又出了问题。百度一下,找到了解决方案。在cmd中先输入
chcp 65001
然后再执行
python -m eel F:\xx\xx\xx\Python_Main.py F:\xx\xx\xx\Web
这下总算是成功打包了。
5、找到我们的Python_Main.exe文件
打包后的文件一般在cmd的启动路径下能够找到。如,我的Python_Main.exe文件就应该在C:\Users\Deadpool里
发现在Deadpool文件里多出了三个文件,分别是Python_Main.spec, dist和build。打开dist后,发现有一个Python_Main文件夹,打。
郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。