[Python] Script kan configuratiebestand niet vinden

Pagina: 1
Acties:

Acties:
  • 0 Henk 'm!

  • Sefyu
  • Registratie: November 2006
  • Niet online
Ik ben bezig met een treingerelateerde applicatie van iemand (zal wel een Tweaker zijn?): https://github.com/geertw/rdt-infoplus-dvs.

Deze applicatie bestaat uit twee delen, één deel ontvangt berichten vanaf een externe server, en het tweede deel biedt een http-interface om de ontvangen berichten weer door te spelen. Deze delen kunnen apart geïnstalleerd worden met Docker met Dockerfile en Dockerfile.api, respectievelijk. Dit topic gaat alleen over het tweede deel, het eerste deel werkt prima namelijk.

Het probleem is dat een stuk Pythonscript een configuratiebestand niet kan vinden, terwijl dit bestand 100% zeker bestaat. Om het probleem zelf proberen op te lossen probeer ik te begrijpen wat er precies gebeurt. De documentatie is helaas niet uitgebreid. Dit is tot waar ik ben gekomen:

In Dockerfile.api staan instructies om een image te bouwen. Na het bouwen kan deze image gedraaid worden in een container, waarbij de app gunicorn gestart wordt met een aantal parameters:

Dockerfile.api
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
FROM python:2.7-slim

COPY *.py /
COPY dvs-http.wsgi dvs-http.py #let op, deze bestanden zijn hetzelfde
COPY requirements.txt .
COPY config/dvs-server.yaml config/dvs-server.yaml
COPY config/http.yaml config/config.yaml
COPY config/http.yaml config/http.yaml

RUN pip install -r requirements.txt
RUN pip install gunicorn

CMD [ "gunicorn", "-b 0.0.0.0:8080", "dvs-http:application" ]

EXPOSE 8080


So far, so good. gunicorn kan starten en begint daarna met dvs-http.py laden. Hier gaat het fout, er verschijnt een foutmelding: Configuratiebestand '-b 0.0.0.0:8080' niet aanwezig

Dit is al vreemd, omdat "-b 0.0.0.0:8080" ook geen configuratiebestand is. Er lijkt iets verkeerds aangeroepen te worden als configuratiebestand. In dvs-http.py, dat geladen wordt door gunicorn, staat:

dvs-http.py
code:
1
2
3
4
5
6
7
8
9
10
11
12
import os, sys
sys.path.insert(0,os.path.dirname(__file__))

import bottle
import dvs_util
import dvs_http_interface

# Load config:
dvs_http_interface.config = dvs_util.load_config(sys.argv[1])
dvs_util.setup_logging(dvs_http_interface.config)

application = bottle.default_app()


De locatie van het configuratiebestand lijkt uit de module dvs_util gehaald te worden (in de module dvs_http_interface staat alleen "config = {}", lijkt mij niet relevant?).

In deze module wordt de laadfunctie van het configuratiebestand gedefineerd.

dvs_util.py
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
def load_config(config_file_path='config/config.yaml'):
    """
    Setup logging configuration
    """

    if os.path.exists(config_file_path):
        try:
            with open(config_file_path, 'r') as config_file:
                config = yaml.load(config_file.read())
        except (yaml.parser.ParserError, yaml.parser.ScannerError) as exception:
            print "YAML fout in config file: %s" % exception
            sys.exit(1)
        except Exception as exception:
            print "Fout in configuratiebestand. Foutmelding: %s" % exception
            sys.exit(1)
    else:
        print "Configuratiebestand '%s' niet aanwezig" % config_file_path
        sys.exit(1)

    return config

Het bestand config/config.yaml bestaat.

Ik denk dat het probleem ligt in het feit dat met sys.argv[1] uit dvs-http.py de eerste optie van het shellcommando gepakt wordt. Die is namelijk '-b 0.0.0.0:8080'.

Als ik namelijk als eerste optie of flag iets anders neerzet, zoals '--log-file voorbeeld.log', dan krijg ik als error Configuratiebestand '--log-file voorbeeld.log' niet aanwezig

Ik heb al een beetje lopen spelen met sys.argv[1], maar ik kan niet bedenken wat daar zou moeten staan. Ik heb geprobeerd:

code:
1
dvs_http_interface.config = dvs_util.load_config(config)

code:
1
dvs_http_interface.config = dvs_util.load_config(config_file)

code:
1
dvs_http_interface.config = dvs_util.load_config()


De eerste twee geven een not_defined-error. De derde blijft hangen (waarschijnlijk wachtend op een parameter).

In Dockerfile.api 'config/config.yaml' als parameter meegeven aan gunicorn werkt ook niet, want gunicorn moet gestart worden met $ gunicorn [OPTIONS] APP_MODULE. Dit zou dan moeten met

code:
1
gunicorn -c config/config.yaml dvs-http:application


Maar dan krijg ik natuurlijk vrolijk Configuratiebestand '-c config/config.yaml' niet aanwezig terug.

Ik ben een volledige newbie als het gaan om Python en unix, Kunnen jullie mij op weg helpen?


Ik weet niet of dit verder nog relevant is, dit alles draait op een VM met daarop Debian 9.

[ Voor 4% gewijzigd door Sefyu op 12-11-2017 01:19 ]


Acties:
  • 0 Henk 'm!

  • DiedX
  • Registratie: December 2000
  • Laatst online: 23:12
En start je de app ook met Docker?

DiedX supports the Roland™, Sound Blaster™ and Ad Lib™ sound cards


Acties:
  • 0 Henk 'm!

  • Morrar
  • Registratie: Juni 2002
  • Laatst online: 22:59
Je denkt in de goede richting. Probleem is inderdaad dat die -d parameter voor gunicorn door het andere script gebruikt wordt als bestandslocatie voor het configuratiebestand.

Om te testen zou je de sys.argv[1] kunnen vervangen door een string met de bestandslocatie, bv "config/config.yaml". Dat zou moeten werken, maar nadeel is dat de locatie dan hardcoded in het script staat.

Wat je eigenlijk moet uitzoeken is hoe je met gunicorn / bottle parameters kunt doorspelen vanaf de commandline. Wellicht heb je hier iets aan: http://docs.gunicorn.org/en/stable/run.html?

[ Voor 20% gewijzigd door Morrar op 12-11-2017 09:05 ]


Acties:
  • 0 Henk 'm!

  • Sefyu
  • Registratie: November 2006
  • Niet online
DiedX schreef op zondag 12 november 2017 @ 06:25:
En start je de app ook met Docker?
Yes, met
[code]docker run -it [image-id]
Morrar schreef op zondag 12 november 2017 @ 09:01:
Je denkt in de goede richting. Probleem is inderdaad dat die -d parameter voor gunicorn door het andere script gebruikt wordt als bestandslocatie voor het configuratiebestand.

Om te testen zou je de sys.argv\[1] kunnen vervangen door een string met de bestandslocatie, bv "config/config.yaml". Dat zou moeten werken, maar nadeel is dat de locatie dan hardcoded in het script staat.

Wat je eigenlijk moet uitzoeken is hoe je met gunicorn / bottle parameters kunt doorspelen vanaf de commandline. Wellicht heb je hier iets aan: http://docs.gunicorn.org/en/stable/run.html?
Ik heb de documentatie nog even doorgespit, maar ben daar niks tegengekomen dat werkt. Ik heb ontdekt dat er twee configuratiebestanden moeten zijn, één voor gunicorn, en één voor de Python-applicatie. Hier heb ik voor gezorgd, én ik heb sys.argv[1] veranderd naar sys.argv[2], én ik heb inderdaad een directe verwijzing naar het configuratiebestand gemaakt.

Gunicorn start ik nu met:

code:
1
gunicorn --config gun_config.py dvs-http


Ik laat het maar even zo, dit heeft me al genoeg hoofdpijn gekost. Thanks :+

Acties:
  • 0 Henk 'm!

  • AW_Bos
  • Registratie: April 2002
  • Laatst online: 01:58

AW_Bos

Liefhebber van nostalgie... 🕰️

@Sefyu Ik heb het overigens wel werkend, maar ik het het met de hand geinstalleerd.
In de vorige versies was er nog geen docker o.i.d. aanwezig.

Onthoud wel dat je voor dit script een gratis abonnement bij het NDOV-loket moet hebben. ZOnder dat kan je geen toegang krijgen tot hun IP-adres om de ZMQ-stream binnen te halen. Je moet dan je IP aan hen doorgeven (1x prod. IP en e.v.t een development omgeving IP), en dan zetten zij de poort open.

Verder vind ik het script heel handig werken.

Over je probleem, vraag de maker anders eens. Die weet misshcien wel wat er mis gaat, zodat die het evt kan patchen.

[ Voor 10% gewijzigd door AW_Bos op 29-11-2017 23:06 ]

Telecommunicatie van vroeger
🚅Alles over spoor en treintjes