Как мне переписать этот код на python для работы в сгенерированном pynstaller exe? - PullRequest
0 голосов
/ 17 декабря 2018

PyInstaller 3.4
Python 3.7
Win 7-64 бит

Я сделал .exe из кода Python, используя PyInstaller, который имеет следующую логику.Цель - запустить http-сервер в новом окне консоли в Windows.Это сделано для того, чтобы избежать блокировки / блокировки основного приложения, и пользователь может просто закрыть недавно запущенное окно консоли, когда они закончат работу с http-сервером.

p = subprocess.call('start "" python  -m http.server --directory {} {} --bind {}'.format(web_server_path, web_server_port, web_bind_ip), shell=True)

Это работает на моем компьютере с Windows, на котором установлен Pythonно, естественно, не работает на ПК без Python.

Поскольку цель состоит в том, чтобы распространить этот .exe среди людей без установки Python, может ли кто-нибудь порекомендовать правильный метод для выполнения вышеуказанного поведения с использованием Python в PyInstaller?Я знаю, что PyInstaller, сгенерированный .exe, по сути работает с интерпретатором Python, но я не знаю, как подключиться к нему с помощью своего кода.

ОБНОВЛЕНИЕ
Требуется, чтобы пользователь мог установить directory, port и address.В идеале также должно быть легко остановиться, просто закрыв окно (отсюда исходный метод командной строки), но его можно изменить.

ДАЛЬНЕЙШЕЕ ОБНОВЛЕНИЕ
Можно ли как-то загрузить python3.dll и напрямую использовать его функцию?ctypes.WinDLL('Path:\to\my.dll')

1 Ответ

0 голосов
/ 17 декабря 2018

Поскольку ваш пример кода предположительно запустил бы веб-сервер, не блокируя дальнейшее выполнение вашего скрипта, вы бы хотели запустить веб-сервер в отдельном потоке.

from sys import version_info
import http.server
import socketserver
from threading import Thread


class WebServer(Thread):
    @staticmethod
    def get_directory_simple_http_request_handler(directory):
        _current_only = version_info < (3, 7)

        class _DirectorySimpleHTTPRequestHandler(http.server.SimpleHTTPRequestHandler):
            _current_only = version_info < (3, 7)

            def __init__(self, *args, **kwargs):
                if not self._current_only:
                    kwargs['directory'] = directory
                super(_DirectorySimpleHTTPRequestHandler, self).__init__(*args, **kwargs)

            @property
            def current_only(self):
                return self._current_only

        return _DirectorySimpleHTTPRequestHandler

    def __init__(self, address='127.0.0.1', port=8000, directory=''):
        self.handler = self.get_directory_simple_http_request_handler(directory)
        self.httpd = socketserver.TCPServer((address, port), self.handler)
        Thread.__init__(self)

    def run(self):
        self.httpd.serve_forever()

    def join(self, *args, **kwargs):
        self.httpd.shutdown()
        super().join(*args, **kwargs)


web_server = None
while True:
    if web_server is None:
        print('Currently not running (type start or exit).')
    else:
        print('Running on:', web_server.httpd.server_address, '(type stop or exit)')
        if web_server.handler.current_only:
            print('Serving current directory, Python <3.7 has no `directory` on SimpleHTTPRequestHandler.')

    command = input('>')

    if command == 'start':
        if web_server is None:
            web_server = WebServer(directory=r'C:\Temp')
            web_server.start()
    if command == 'stop':
        if web_server is not None:
            web_server.join()
            web_server = None
    if command == 'exit':
        exit(0)

Обратите внимание, что Python 3.7первая версия, поддерживающая параметр directory, более ранние версии Python будут обслуживать только текущий каталог процесса.

Заводской статический метод предназначен для установки отдельного экземпляра SimpleHTTPRequestHandler, который получаетинициализируется с нужным каталогом.

Если вы предпочитаете просто запустить консольное окно, запустив (тестовый) веб-сервер Python (или другой внешний сервер, если Python недоступен):

import time
from subprocess import Popen, CREATE_NEW_CONSOLE

proc = Popen(['python', '-m', 'http.server', '8000'],
             cwd=r'C:\temp',
             creationflags=CREATE_NEW_CONSOLE, close_fds=True)

while True:
    print('Running')
    time.sleep(2)

Аналогично, если вам нравится тихий режим, но вам не нужен доступ к объекту веб-сервера, это также работает:

import time
from subprocess import Popen

proc = Popen(['python', '-m', 'http.server', '8000'], close_fds=True, cwd=r'C:\temp')

while True:
    print('Running')
    time.sleep(2)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...