Сообщение об ошибке: «TypeError: необязательный метод w () должен быть вызван с экземпляром журнала в качестве первого аргумента (вместо этого получен экземпляр str)» - PullRequest
0 голосов
/ 10 июля 2019

Мой скрипт работал пару дней назад, теперь у меня несколько проблем с ним. Сначала у меня был один, но я получил эту ошибку, теперь я пытаюсь запустить ее и получить эту ошибку.

Traceback (most recent call last):
  File "rt.py", line 450, in <module>
    start()
  File "rt.py", line 136, in start
    load()
  File "rt.py", line 124, in load
    loadCookies()
  File "rt.py", line 107, in loadCookies
    log.w("No cookie file found. Please login.")
TypeError: unbound method w() must be called with log instance as first argument (got str instance instead)

Я пытаюсь опубликовать весь код здесь, но он не позволяет мне работать над его созданием. Пожалуйста посоветуй. Было ли обновление, которое я пропустил в python, или что вдруг пошло не так, я использую это уже много лет.

import sys
import os
import traceback
import pickle
import time
import random


class log:
    def i(msg, *arg):
        print("\nINFO :: " + str(msg).format(*arg))

    def w(msg, *arg):
        print("\nWARNING :: " + str(msg).format(*arg))

    def E(msg, *arg):
        print("\nERROR :: " + str(msg).format(*arg))

    def Q(msg, *arg):
        print("\nFATAL ERROR :: " + str(msg).format(*arg))
        input("Program needs to be shutdown. Press Enter ...")
        sys.exit(1)


try:
    from selenium import webdriver
    from selenium.webdriver.common.keys import Keys
    from selenium.webdriver.common.by import By
    from selenium.webdriver.common.action_chains import ActionChains
    from selenium.common.exceptions import *
except ImportError:
    log.i("http://selenium-python.readthedocs.io/installation.html")
    log.Q("Selenium and Selenium Chrome webdriver must be installed on your system to run this program.")

# Will contain the tweets that need to be retweeted
rtLinks = []
rtDone = []
failed = []
_Loaded = False

try:
    driver = webdriver.Chrome()
except:
    log.i("https://sites.google.com/a/chromium.org/chromedriver/downloads")
    log.Q("Could not load Chrome. Please install Chrome webdriver and add it to the environment PATH.")

driver.set_window_size(760,800)


# Saving and loading data
#########################################################################

_datapath = os.getcwd()

_Cookies = os.path.join(_datapath, "DMautoRt_cookies.pkl")
_Retweeted = os.path.join(_datapath, "DMautoRt_retweeted.txt")
_UnRetweeted = os.path.join(_datapath, "DMautoRt_notretweeted.txt")

def loadRetweeted():
    global rtDone
    if not os.path.exists(_Retweeted):
        return
    fh = open(_Retweeted)
    rtDone = [l.strip() for l in fh.readlines()]
    fh.close()
    log.i("Loaded Retweeted items [{}].", len(rtDone))

def loadNotRetweeted():
    global rtLinks
    if not os.path.exists(_UnRetweeted):
        return
    fh = open(_UnRetweeted)
    rtLinks = [l.strip() for l in fh.readlines()]
    fh.close()
    log.i("Loaded Not Retweeted items [{}].", len(rtLinks))

def saveRetweeted():
    count = 0
    fh = open(_Retweeted, 'w')
    for link in rtDone:
        link = link.strip()
        if "/FindomToday/" in link:
            continue
        if len(link) > 7:
            count += 1
            fh.write("{}\n".format(link))
    fh.close()
    log.i("Saved Retweeted items. [{}]", count)

def saveNotRetweeted():
    count = 0
    fh = open(_UnRetweeted, 'w')
    for link in rtLinks:
        link = link.strip()
        if len(link) > 7:
            count += 1
            fh.write("{}\n".format(link))
    fh.close()
    log.i("Saved Not Retweeted items. [{}]".format(count))

def saveCookies():
    pickle.dump(driver.get_cookies(), open(_Cookies, 'wb'))
    log.i("Saved Cookies.")

def loadCookies():
    if not os.path.exists(_Cookies):
        log.w("No cookie file found. Please login.")
        return
    cookies = pickle.load(open(_Cookies, "rb"))
    for cookie in cookies:
        driver.add_cookie(cookie)
    log.i("Loaded Cookies.")


# Begining and Ending Procedures
#########################################################################

def load():
    global _Loaded
    if not os.path.exists(_datapath):
        os.mkdir(_datapath)
    loadRetweeted()
    loadNotRetweeted()
    loadCookies()
    _Loaded = True

def save():
    if not os.path.exists(_datapath):
        os.mkdir(_datapath)
    saveCookies()
    saveRetweeted()
    saveNotRetweeted()

def start():
    home()
    load()
    time.sleep(2)
    messages()

def shutdown():
    log.i("Shutting down. Please wait ...")
    if _Loaded:
        save()
    driver.close()
    log.i("Goodbye.")

# Help functions
#########################################################################

def help():
    print("""
        Usage:
        ======
        Once you run the program, twitter will load. Login.

        Once you are on a group DM page, run 'parse()'.

        To RT the parsed tweets, run "rtAll()".

        Run "status()" to show number of tweets on the queue.

        To close the program run "quit()".

        Just type in any function name and press ENTER.

        Run parse() multiple times if needed. You can also check if any new link has been
        added by running this function.

        Try running 'functions()' for a list of available functions.

        Try running 'issues()' for a list of known issues.

        You can run any python command just like an interpreter.
        For any issues or suggestions please DM the Author @DIY on Twitter.

        Sharing is caring, please share this program with other promoters.

        Licensed under CC BY-NC-ND 4.0 (https://creativecommons.org/licenses/by-nc-nd/4.0/)

    """)


def functions():
    print("""
        Available Functions:
        ===================
        Try running the following functions.

        rtFailed()
        home()
        status()
        rtAll()
        checkedRt()
        retweet()
        tlRt(5)
        login()
        messages()
        save()
        load()
        emiliaa()
        jazzy()
        fdToday()

    """)

def issues():
    print("""
        Known Issues:
        ============
        1. Google Chrome v63 has a bug that prints error messages on the console.
        That is not produced by this program or selenium.

        2. Even after the shutdown command, the console window remains open.
        You can manually close it.

        3. After starting a rtAll() loop, it's still not possible to terminate it.
        Pressing KeyboardInterrupt will close the browser itself.

        4. The program waits a random amount of 1 to 5 seconds before retweeting the next tweet.
        Too many retweets within a short interval may raise flags to twitter and lead to
        your account suspension.

        """)

# Navigation Helpers
#########################################################################

def login():
    driver.get("https://mobile.twitter.com/login")

def home():
    driver.get("https://mobile.twitter.com/")

def messages():
    driver.get("https://twitter.com/messages")

def dailydose():
    driver.get("https://twitter.com/FindomToday/lists/dailydose")

def emiliaa():
    driver.get("https://twitter.com/GoddessEmiliaa")

def jazzy():
    driver.get("https://twitter.com/yourqueenjazzy")

def fdToday():
    driver.get("http://twitter.com/FindomToday")


# Retweet Methods
#########################################################################

def status():
    log.i("{} remaining, {} retweeted, {} failed.".format(len(rtLinks), len(rtDone), len(failed)))
    print("=======================================")

def checkRetweet():
    try:
        replybox = driver.find_element(By.XPATH, "//div[@class='inline-reply-tweetbox-container']")
    except NoSuchElementException:
        time.sleep(2)
        # try again
        try:
            replybox = driver.find_element(By.XPATH, "//div[@class='inline-reply-tweetbox-container']")
        except NoSuchElementException:
            log.w("Couldn't find the reply box. Assuming unretweeted.")
            return False

    tweetmodal = replybox.find_element(By.XPATH, "..")

    foot = tweetmodal.find_element(By.XPATH, ".//div[@class='permalink-footer']")
    btns = foot.find_element(By.XPATH, "..")

    rts = btns.find_elements(By.XPATH, ".//button[@data-modal='ProfileTweet-retweet']")

    if len(rts) > 2:
        log.E("Failed to check if retweeted or not. Assuming unretweeted.")
        return False

    for b in rts:
        if "Retweeted" in b.text:
            # already retweeted
            return True
    return False


def retweet(check=False):
    if "/status/" not in driver.current_url:
        log.E("Not a tweet page.")
        return True

    if "Twitter / ?" in driver.title:
        log.E("Tweet is missing. URL: {}", driver.current_url)
        return True

    if '/FindomToday/' not in driver.current_url and checkRetweet():
        log.i("Already retweeted. Remaining {}", len(rtLinks))
        return True

    if check:
        time.sleep(1)
        if input("Retweet this? Enter any value to skip.  "):
            log.i("Skipped. Remaining {}", len(rtLinks))
            return True

    body = driver.find_element(By.XPATH, "//body")

    # LIKE
    body.send_keys("l")

    # RETWEET
    body.send_keys("t")
    body.send_keys("t")

    time.sleep(1)

    try:
        modal = driver.find_element(By.XPATH, "//div[@id='retweet-tweet-dialog-dialog']")
        modal.find_element(By.XPATH, ".//div[@class='tweet-button']").click()
    except:
        log.E("Could not find tweet dialog. Make sure your tab is open and you are not using other tabs.")
        return False
    else:
        log.i("Retweeted. Remaining {}", len(rtLinks))
        return True

# Manually add to retweeted list
def addRtDone():
    rtDone.append(driver.current_url)
    log.i("Added {}", driver.current_url)


def rtAll(count=0, wait=5, check=False):
    if count == 0 or count > len(rtLinks):
        count = len(rtLinks)
    log.i("Retweeting {} tweets ... ", count)

    if wait < 5: wait = 5
    log.i("Will wait {} to {} seconds between each retweet.", wait-4, wait)

    try:
        while count > 0:
            link = rtLinks.pop()
            if link in rtDone:
                continue

            log.i("Processing URL: {}", link)
            driver.get(link)

            if not retweet(check):
                failed.append(link)
                log.E("{} failed retweet.", link)

            else:
                if link not in rtDone:
                    rtDone.append(link)
                if driver.current_url not in rtDone:
                    rtDone.append(driver.current_url)

            count -= 1
            time.sleep(random.uniform(wait-4, wait))


        log.i("All Retweeted. {} failed.", len(failed))
        if len(failed) > 0:
            log.i("Try running rtFailed() to try retweeting the failed ones again.")

    except (KeyboardInterrupt, SystemExit):
        print("Keyboard Interrupt")
        print("{} failed, {} remaining.".format(len(failed), len(rtLinks)))

def rtFailed(check = False):
    if len(failed) < 1:
        log.i("No failed retweets found.")
        return
    rtLinks = failed
    rtAll(check)

def checkedRt():
    log.i("This function will ask for your permission before retweeting each of the tweets.")
    rtAll(True)

# Parse messages for new links

def parse():
    newlink = 0
    dock = driver.find_element(By.XPATH, "//div[@class='DMDock']")
    dmc = dock.find_elements(By.XPATH, ".//div[@class='DirectMessage-contentContainer']")
    dmc += dock.find_elements(By.XPATH, ".//div[@class='QuoteTweet-container']")
    for dm in dmc:
        links = dm.find_elements(By.XPATH, ".//a")
        for a in links:
            href = a.get_attribute("href").strip()
            if href and ("/status/" in href or "/t.co/" in href):
                if (href not in rtLinks) and (href not in rtDone):
                    rtLinks.append(href)
                    newlink += 1
                    log.i("New Tweet: {}", href)
    log.i("{} new links found.".format(newlink))


# Timeline Retweet Methods
#########################################################################

def tlRt(n=10):
    body = driver.find_element(By.XPATH, "//body")
    while n:
        try:
            body.send_keys("j")
            body.send_keys("l")
            time.sleep(0.5)
            body.send_keys(Keys.ENTER)

            n -= 1
            time.sleep(1)

            if retweet():
                log.i("{} tweets retweeted.".format(driver.current_url))
            else:
                log.E("{} retweets failed.".format(driver.current_url))

            time.sleep(1)
            body.send_keys(Keys.ESCAPE)
            time.sleep(0.5)
        except (KeyboardInterrupt, SystemExit):
            break



# Maintainence
#########################################################################
VERSION = "1.0.1"

def changelog():
    print("""
        Initial release. Version {}.
        """.format(VERSION))

print("""

    Welcome! DM Auto ReTweeter Version {}
    ===========================================================
    For any information or issues contact @DIY on Twitter.
    Enter 'help' for detailed instructions on using the program.
    ===========================================================""".format(VERSION))

# Main control flow
#########################################################################

start()

while True:
    cmd = input(">> ")
    if cmd.strip() in ["exit", "close", "quit", "shutdown", "exit()", "quit()", "shutdown()"]:
        shutdown()
        break

    if cmd.strip() in ["help", "help()", "about", "version", "about()", "version()"]:
        help()
        continue

    try:
        exec(cmd)

    except (KeyboardInterrupt, SystemExit):
        print("Keyboard Interrupt")
        pass

    except Exception:
        print()
        traceback.print_exc(file=sys.stdout)
        print()

1 Ответ

1 голос
/ 10 июля 2019

Вы используете определение class, как если бы оно было соответствующим ему экземпляром.Функция log.w (как и другие методы в журнале) - это методы класса, которые получают в качестве первого параметра сам экземпляр (то, что обычно называется аргументом self, который вводится автоматически).Вы можете использовать его как обычные методы и создавать такие классы:

class log:
    def i(self, msg):
        print(msg)

log_instance = log()
log_instance.i('Hello world')

или использовать статические методы, которые не получают метод self:

class log:
    @staticmethod
    def i(msg):
        print(msg)

log.i('Hello world')

В любом случае, вы можете захотетьрассмотреть возможность использования logging из стандартной библиотеки Python для ведения журналов.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...