2013-01-22 22 views
6

Czy istnieje sposób na uruchomienie ochrony przed plikiem wykonywalnym utworzonym za pomocą programu piorącego? Próbowałem po prostu uruchamiać go tak, jakby był skryptem w języku Pythona i nie podoba mi się plik wykonywalny jako dane wejściowe (nie spodziewałem się, że to zadziała) i podejrzewam, że odpowiedź brzmi: nie, nie ma łatwego sposobu na uruchomienie ochrony przed zbudowanym plikiem wykonywalnym .... (jest na okna .exe)pokrycie zmrożonego pliku wykonywalnego

pakiet pokrycia używam jest tylko normalny pakiet pokrycie, które można uzyskać z „easy_install pokrycia” z nedbatchelder.com (http://nedbatchelder.com/code/coverage/)

+0

Jakie narzędzia do obsługi kodu są używane w skryptach Pythona, które nie są upieczone do pliku wykonywalnego? – selbie

+0

edytowane w celu uwzględnienia tych informacji –

+1

Co chcesz przetestować? Czy masz nie tylko dostęp do niezamrożonych skryptów, które można uruchomić na pokrycie? –

Odpowiedz

6

Ten ISN” w pełni sformułowaną odpowiedź, ale co znalazłem do tej pory.

Z mojego rozumienia tego, jak działa Pyinstaller, wynika, że ​​plik binarny jest zbudowany z małego programu C, który osadza interpretera pytona i bootstraps ładujący skrypt. Konstruktor EXE PyInstaller zawiera archiwum po końcu rzeczywistego pliku binarnego zawierającego zasoby dla kodu Pythona. Zostało to wyjaśnione tutaj http://www.pyinstaller.org/export/develop/project/doc/Manual.html#pyinstaller-archives.

Istnieje iu.py z Pyinstaller/loader/iu.py Docs. Powinieneś być w stanie stworzyć hak importu do importu z pliku binarnego. Googling dla disassemblera aplikacji Pyinstaller znalezionego https://bitbucket.org/Trundle/exetractor/src/00df9ce00e1a/exetractor/pyinstaller.py, który wygląda na to, że może wyodrębnić niezbędne części.

Inna część tego polega na tym, że wszystkie zasoby w archiwum binarnym zostaną skompilowane z kodu Pythona. Najprawdopodobniej report.py da ci niepotrzebne dane wyjściowe w taki sam sposób, jak przy uderzaniu w inny skompilowany moduł podczas pracy w normalnych warunkach.

3

Highlight użycie cover_pylib=True

wiem, że to długo po poprosił Cię pytanie, ale jestem po prostu poruszanie się do konieczności odpowiedzi. :)

Używanie bieżącego źródła bitów do coverage.py Jestem w stanie pomyślnie zebrać dane dotyczące zasięgu z pliku EXE wygenerowanego przez PyInstaller.

W głównym źródłem dla mojej aplikacji warunkowo powiedzieć zasięg, aby rozpocząć zbieranie pokrycie tak:

if os.environ.has_key('COVERAGE') and len(os.environ['COVERAGE']) > 0: 
    usingCoverage = True 
    import coverage 
    import time 
    cov = coverage.coverage(data_file='.coverage.' + version.GetFullString(), data_suffix=time.strftime(".%Y_%m_%d_%H_%M.%S", time.localtime()), cover_pylib=True) 
    cov.start() 

ten rozpoczyna zbieranie pokrycia Dopiero kiedy zapragniesz. Użycie sufiksu data_ffix pozwala mi łatwiej wykorzystać cov.combine() do późniejszego scalania plików pokrycia. version.GetFullString() to tylko numer mojej aplikacji.

cover_pylib jest ustawiony na True tutaj w bo wszystkie standardowe moduły Python Library __file__ atrybut wyglądać następująco ...\_MEIXXXXX\random.pyc a więc są nie do odróżnienia (na podstawie ścieżki) z innym kodem, który nie istnieje wewnątrz opakowania.

Gdy aplikacja jest gotowa do wyjścia mam ten mały fragment:

if usingCoverage: 
    cov.stop() 
    cov.save() 

Raz mój wniosek został uruchomiony coverage.py nadal nie będzie automatycznie wygenerować raport HTML dla mnie. Dane pokrycia muszą zostać wyczyszczone, aby odwołania do plików ...\_MEIXXXX\... zostały przekształcone w bezwzględne ścieżki plików do rzeczywistego kodu źródłowego.

to zrobić uruchamiając ten fragment kodu:

import sys 
import os.path 

from coverage.data import CoverageData 
from coverage import coverage 

from glob import glob 

def cleanupLines(data): 
    """ 
    The coverage data collected via PyInstaller coverage needs the data fixed up 
    so that coverage.py's report generation code can analyze the source code. 
    PyInstaller __file__ attributes on code objecters are all in subdirectories of the  _MEIXXXX 
    temporary subdirectory. We need to replace the _MEIXXXX temp directory prefix with  the correct 
    prefix for each source file. 
    """ 
    prefix = None 
    for file, lines in data.lines.iteritems(): 
     origFile = file 
     if prefix is None: 
      index = file.find('_MEI') 
      if index >= 0: 
       pathSepIndex = file.find('\\', index) 
       if pathSepIndex >= 0: 
        prefix = file[:pathSepIndex + 1] 
     if prefix is not None and file.find(prefix) >= 0: 
      file = file.replace(prefix, "", 1) 
      for path in sys.path: 
       if os.path.exists(path) and os.path.isdir(path): 
        fileName = os.path.join(path, file) 
        if os.path.exists(fileName) and os.path.isfile(fileName): 
         file = fileName 
      if origFile != file: 
       del data.lines[origFile] 
       data.lines[file] = lines 

for file in glob('.coverage.' + version.GetFullString() + '*'): 
    print "Cleaning up: ", file 
    data = CoverageData(file) 
    data.read() 
    cleanupLines(data) 
    data.write() 

Pętla for jest tu wyłącznie w celu zapewnienia wszystkich plików pokrycia, które zostaną połączone są czyszczone.

UWAGA: Jedyne dane dotyczące zasięgu, które domyślnie nie są usuwane z tego kodu, to PyInstaller powiązane pliki, które nie zawierają danych _MEIXXX w ich atrybutach __file__.

Możesz teraz z powodzeniem generować raport HTML lub XML (lub coś podobnego) coverage.py zgłosić normalny sposób.

W moim przypadku wygląda to tak:

cov = coverage(data_file='.coverage.' + version.GetFullString(), data_suffix='.combined') 
cov.load() 
cov.combine() 
cov.save() 
cov.load() 
cov.html_report(ignore_errors=True,omit=[r'c:\python27\*', r'..\3rdParty\PythonPackages\*']) 

Zastosowanie data_file w konstruktorze jest zapewnienie, że ładunek/połączyć rozpozna wszystkie moje wyczyszczoną plików pokrycia poprawnie.

Zadzwoń pod numer , aby zignorować standardowe biblioteki python (i biblioteki Python zaznaczone w moim drzewie kontroli wersji) i skupić się tylko na kodzie aplikacji.

Mam nadzieję, że to pomoże.

Powiązane problemy