Вызов оболочки с использованием Tkinter filedialog имеет ограничение на количество файлов, которые могут быть загружены до сбоя - PullRequest
0 голосов
/ 20 марта 2019

У меня есть форма Access VBA, которую я использую для запуска (посредством вызова оболочки) модуля Python, который загружает несколько файлов, выбранных из файлового диалога Tkinter, в базу данных SQL Server.

из Access

При запуске из Access я заметил следующее:

  • Для небольшого количества файловэто работает хорошо, запускает модули Python, которые, в свою очередь, запускают некоторые процедуры T-SQL, а затем возвращают идентификатор для первой загруженной даты и времени (оба целых числа)

  • за умеренное количествофайлов данные загружаются в таблицы SQL Server корректно, но идентификаторы не возвращаются, и программа VBA «зависает» до закрытия окна Python

  • Для большого количества файловданные не загружаются в таблицы SQL Server, идентификаторы не возвращаются и программа VBA останавливается до закрытия окна Python

из Python

С некоторыми незначительными изменениями модуля Python (замена списка sys.argv на жестко типизированный список и аргумент, как видно из закомментированных строк кода в модуле Python)может инициировать выполнение из Python, и наблюдается следующее:

  • Для любого количества файлов данные загружаются в таблицы SQL Server, возвращаются идентификаторы, и программа успешно завершается соответствующим образом

Исследования и испытания Я прошел через множество похожих вопросов о переполнении стека здесь и здесь .Многие из проблем, поднятых в этих темах, связаны с возвращением строки filedialog askopenfilenames, возвращающей строку вместо кортежа, и многочисленными способами преобразования строки в список или кортеж с использованием splitlist, regex и т. Д. Я не обнаружил, что это таквместо этого обнаружив, что filedialog ведет себя так, как ожидалось, и возвращает последовательность строк в виде кортежа, который я преобразовал в список, чтобы предоставить аргумент правильного типа вызываемому модулю.

Код доступа

Function FileUpload(int1Update As Integer, int2Update As Integer, int3Update 
                    As Integer, int4Update As Integer)
    Dim objShell As Object, objExec As Object, objOutput As Object
    Dim strPython As String, strFile As String, strShell As String, 
    Dim strOutput As String
    Dim intAuto As Integer, intCnt1 As Integer

    Set objShell = CreateObject("WScript.Shell")

    intAuto = 0
    strPython = "C:\Program Files\Microsoft SQL 
                     Server\MSSQL14.SQLSERVER2017\PYTHON_SERVICES\python.exe "
    strFile = "C:\Users\dun__\source\repos\MainApp\MainApp\GetFiles.py "

    strShell = strPython & strFile & intAuto & " " & int1Update & " " & _
               int2Update & " " & int3Update & " " & int4Update

    Debug.Print "objShell.exec(" & strShell & ")"
    Set objExec = objShell.exec(strShell)  'execute shell command to python
    Set objOutput = objExec.StdOut  'obtain standard output from the shell 
                                    'command

    strOutput = objExec.StdOut.ReadAll

    MsgBox "Results of the shell execution:" & vbCrLf & strOutput

    Set objOutput = Nothing
    Set objShell = Nothing
    Set objExec = Nothing

End Function

Код Python

import tkinter
from tkinter import filedialog
import sys
from MainApp import server_uploads

root = tkinter.Tk()
root.withdraw()
file_dir = r'C:\Users\dun__\Google Drive\Programming Stuff'
dnld_flnm = []
while not dnld_flnm:
    dnld_flnm = list(filedialog.askopenfilenames(parent=root, 
                     initialdir=file_dir,title='Please select the files'\
                     ' you wish to upload.'))
    if dnld_flnm:
        during_day = 0
        auto_run = int(sys.argv[1])
        rtrn_date, rtrn_time = server_uploads(dnld_flnm, during_day, 
                                              auto_run, sys.argv)
        #auto_run = 0 #delete when tested
        #manparams = ['', 0, 0, 0, 0, 0] #delete when tested
        #rtrn_date, rtrn_time = server_uploads(dnld_flnm, during_day, 
        #                                      auto_run, manparams)
        if rtrn_time == '':
            print('\nFirst DateNo uploaded in batch: %d' % rtrn_date)
        else:
            print('\nFirst DateNo uploaded in batch %d.\n\n TimeNo '\ 
                  'uploaded %d.\n\n' % (rtrn_date, rtrn_time))
    else:
    print('Please select some files for uploading.')

Вопрос

Кто-нибудь сможет объяснить, что вызываетнесоответствие между поведением, наблюдаемым при инициировании загрузки из Python (работает для любого количества выбранных файлов), и инициированием с помощью команды оболочки из Access VBA в Python (работает для небольшого числа файлов -> частично работает для умеренного количества файлов -> вообще не работает для большого количества файлов)?Обратите внимание, что наблюдаемое поведение не совпадает с наблюдаемым в вопросах о переполнении стека с гиперссылкой, где различные методы были предложены для получения кортежа строк filepath в качестве вывода из файла диалога tkinter.Код выше уже успешно генерирует кортеж строк filepath.

...