cx_Freeze exe - Blogger API funktioniert nicht / keine Error

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
Zoja
User
Beiträge: 145
Registriert: Freitag 28. Februar 2014, 14:04

Hallo mal wieder!

Ich habe mein Tool so gut wie fertig, habe jetzt eine exe daraus erstellt mit cx_Freeze, hat für die Wordpress APi und Tumblr API wunderbar geklappt, jedoch nicht für die Google Blogger API. Ohne exe funktioniert alles, sobald ich die exe erstelle, funktioniert das Posten nicht.

Für die Blogger API brauche ich meine Oauth2 Zugangsdaten, die ich aus der JSON lade, das klappt auch, ich werde redirceted via Broswer und erlaube den Zugriff auf die Blogger API (diese ist auch aktiviert). Jetzt müsste eine blogger.dat Datei im selben Ordner erstellt werden, jedoch passiert nichts, obwohl da steht, dass die Authentifizierung erfolgreich war. Füge ich die blogger.dat manuel rein, wird diese erkannt, denn ich werde nicht redirected, aber wenn ich posten will tut sich nichts auch keine errors.

Für die Authentifizierung benutze ich diesen Code (war von google vorgegeben):

Code: Alles auswählen

#!/usr/bin/env python
# -*- coding: utf-8 -*-

from __future__ import print_function
import sys
from oauth2client import client
from googleapiclient import sample_tools

# Authenticate and construct service.
def google_blogger_zugangsdaten():

    global service
    service, flags = sample_tools.init(
    sys.argv, 'blogger', 'v3', __doc__ , "client_secrets.json",
    scope='https://www.googleapis.com/auth/blogger')


def google_blogger_execute(google_blogname, bild_uri_zum_posten, alt_attribut_bild, title_attribut_bild, google_post_title, google_post_content):

    blogs = service.blogs()
    thisusersblogs = blogs.listByUser(userId='self').execute()
    for blog in thisusersblogs['items']:
        print('The blog named \'%s\' is at: %s id is: %s' % (blog['name'], blog['url'], blog['id']))

    posts = service.posts()

    #blog_id = 0
    #google_blogname = "Development Blog"
    for blog in thisusersblogs['items']:
        if blog['name'] == google_blogname:
            #blog_id = blog['id']

            request = posts.insert(blogId=blog['id'], body = {"title" : google_post_title, "content" :  "<img src='" + bild_uri_zum_posten + "' title='" + title_attribut_bild + "' alt='" + alt_attribut_bild + "'><br>" + google_post_content})
            request.execute()
Ich hatte auch schon versucht __doc__ zu blogger.dat zu verändern. Meine Vermutung ist, dass da irgendetwas mit den Pfaden nicht stimmt, denn nachdem ich die exe erstelle ändert sich auch einiges, wobei auch wenn ich die blogger.dat in der setup.py bei include reintue passiert nichts.

meine setup.py, die zu cx_Freeze gehört:

Code: Alles auswählen

import sys
from cx_Freeze import setup, Executable
exe = Executable(
    script=r"interface_gui.py",
    base="Win32GUI",
    )

setup(
    name = "TESTApp",
    version = "0.1",
    description = "An example",
    options = {"build_exe": {"includes": "BaseHTTPServer", "include_files": ["data.json", "client_secrets.json", "google_zugang.json", "tumblr_credentials.json", "blogger.dat"]} },
    executables = [exe]
    )
Und so sieht die Struktur in dem exe Ordner aus:
Bild

Vielen Dank!
BlackJack

@Zoja: Das `__doc__`-Argument ist ja nicht das Problem sondern das `name`-Argument. Daraus bildet die `sample_tools.init()`-Funktion den Dateinamen für die `blogger.dat` die sie schreibt. Und zwar wie's aussieht im aktuellen Arbeitsverzeichnis. Und welches das genau ist, hängt davon ab wie man das Programm startet. Ist irgendwie keine gute Idee das so zu machen. Das da Kommandozeilen-Optionen und -Argumente parsen mit in der `init()` drin steckt ist auch unschön. Eine Funktion sollte *eine* Aufgabe erledigen und nicht zwei (oder mehr) verschiedene.
Zoja
User
Beiträge: 145
Registriert: Freitag 28. Februar 2014, 14:04

Code: Alles auswählen

# Copyright (C) 2013 Google Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#      http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

"""Utilities for making samples.

Consolidates a lot of code commonly repeated in sample applications.
"""

__author__ = 'jcgregorio@google.com (Joe Gregorio)'
__all__ = ['init']


import argparse
import httplib2
import os

from apiclient import discovery
from oauth2client import client
from oauth2client import file
from oauth2client import tools


def init(argv, name, version, doc, filename, scope=None, parents=[]):
  """A common initialization routine for samples.

  Many of the sample applications do the same initialization, which has now
  been consolidated into this function. This function uses common idioms found
  in almost all the samples, i.e. for an API with name 'apiname', the
  credentials are stored in a file named apiname.dat, and the
  client_secrets.json file is stored in the same directory as the application
  main file.

  Args:
    argv: list of string, the command-line parameters of the application.
    name: string, name of the API.
    version: string, version of the API.
    doc: string, description of the application. Usually set to __doc__.
    file: string, filename of the application. Usually set to __file__.
    parents: list of argparse.ArgumentParser, additional command-line flags.
    scope: string, The OAuth scope used.

  Returns:
    A tuple of (service, flags), where service is the service object and flags
    is the parsed command-line flags.
  """
  if scope is None:
    scope = 'https://www.googleapis.com/auth/' + name

  # Parser command-line arguments.
  parent_parsers = [tools.argparser]
  parent_parsers.extend(parents)
  parser = argparse.ArgumentParser(
      description=doc,
      formatter_class=argparse.RawDescriptionHelpFormatter,
      parents=parent_parsers)
  flags = parser.parse_args(argv[1:])

  # Name of a file containing the OAuth 2.0 information for this
  # application, including client_id and client_secret, which are found
  # on the API Access tab on the Google APIs
  # Console <http://code.google.com/apis/console>.
  client_secrets = os.path.join(os.path.dirname(filename),
                                'client_secrets.json')

  # Set up a Flow object to be used if we need to authenticate.
  flow = client.flow_from_clientsecrets(client_secrets,
      scope=scope,
      message=tools.message_if_missing(client_secrets))

  # Prepare credentials, and authorize HTTP object with them.
  # If the credentials don't exist or are invalid run through the native client
  # flow. The Storage object will ensure that if successful the good
  # credentials will get written back to a file.
  storage = file.Storage(name + '.dat')
  credentials = storage.get()
  if credentials is None or credentials.invalid:
    credentials = tools.run(flow, storage, flags)
  http = credentials.authorize(http = httplib2.Http())

  # Construct a service object via the discovery service.
  service = discovery.build(name, version, http=http)
  return (service, flags)
hier ist googles sample_tools Klasse, aber ich sehe absolut keinen Grund warum es in der .exe nicht mit der blogger.dat funktioniert
Der nimmt einfach nur den name, also blogger und klebt da .dat dran und verändern keinen path, müsste also in den root directoty legen, god damn google!

[EDIT] Ich habe eine Idee woran es liegt, ich muss die Storage Klasse bei "includes" in der setup.py reinpacken, das muss es sein! Ich probier es aus
BlackJack

@Zoja: Was meinst Du mit ”root”? Welches ist denn das aktuelle Arbeitsverzeichnis wenn Du die EXE startest? Das hast Du doch nur bedingt in der Hand, und es kann auch davon abhängen *wie* Du die EXE startest. Bei so einem unverhersehbaren Pfad eine Datei anzulegen oder zu erwarten ist halt keine gute Idee.
Zoja
User
Beiträge: 145
Registriert: Freitag 28. Februar 2014, 14:04

BlackJack hat geschrieben:@Zoja: Was meinst Du mit ”root”? Welches ist denn das aktuelle Arbeitsverzeichnis wenn Du die EXE startest? Das hast Du doch nur bedingt in der Hand, und es kann auch davon abhängen *wie* Du die EXE startest. Bei so einem unverhersehbaren Pfad eine Datei anzulegen oder zu erwarten ist halt keine gute Idee.
So ich der root directory ist doch immer gleich, da wo die exe liegt und alle json dateien. habs ganz oben gepostet.

Aber Ich bin jetzt weiter gekommen: ich habe diese Library.zip da liegen alle .pyc Dateien. Jetzt verlangt er, dass ich die client_secrets.json auch da rein packe, aber das geht anscheinend nicht oder?
jedenfalls das ist die library.zip:
Bild

und das ist jetzt der error, aber der kommt auch, wenn die json datei drin liegt:
Bild
BlackJack

@Zoja: Das was Du da als ”root”-Verzeichnis bezeichnest muss nicht das aktuelle Arbeitsverzeichnis sein für den Prozess. Das kann sonstwas sein. Wenn Du eine Datei relativ zu einer Moduldatei haben möchtest dann musst Du das selber aktiv ermitteln, zum Beispiel anhand des `__file__`-Wertes im Modul mit `os.path.dirname()` und eventuell `os.path.join()` und einer relativen Pfadangabe zum Modul. Und dann kannst Du die `init()`-Funktion nicht verwenden denn die ist so unpraktisch das sie eben einfach vom aktuellen Arbeitsverzeichnis für eine Konfigurationsdatei ausgeht. Das ist Grütze. Falls das ”Verzeichnis” mit den Dateien innerhalb einer ZIP-Datei liegt hast Du noch mal extra Probleme.
Zoja
User
Beiträge: 145
Registriert: Freitag 28. Februar 2014, 14:04

BlackJack hat geschrieben:@Zoja: Das was Du da als ”root”-Verzeichnis bezeichnest muss nicht das aktuelle Arbeitsverzeichnis sein für den Prozess. Das kann sonstwas sein. Wenn Du eine Datei relativ zu einer Moduldatei haben möchtest dann musst Du das selber aktiv ermitteln, zum Beispiel anhand des `__file__`-Wertes im Modul mit `os.path.dirname()` und eventuell `os.path.join()` und einer relativen Pfadangabe zum Modul. Und dann kannst Du die `init()`-Funktion nicht verwenden denn die ist so unpraktisch das sie eben einfach vom aktuellen Arbeitsverzeichnis für eine Konfigurationsdatei ausgeht. Das ist Grütze. Falls das ”Verzeichnis” mit den Dateien innerhalb einer ZIP-Datei liegt hast Du noch mal extra Probleme.
Vielen Dank BlackJack! Ich weiß jetzt was ich zu tun habe, hört sich nach nerviger Arbeit an :( goddamn google!
Antworten