有没有更好的方法来组织Python(3.6.2)文件?

时间:2019-04-06 01:49:41

标签: python

摘要。

我有两个python文件。第一个读取一些输入(文本),第二个存储一些功能。这里的问题是我用来查找所需功能的方法。现在,我正在使用If / Elif方法比较输入和函数,但是此方法需要将存储在第二个文件中的所有函数与输入进行比较,我在考虑是否“这是最好的方法吗?”

完整说明。

我正在尝试构建一个Telegram聊天机器人,只是为了练习一些Python。在开始之前,我先绘制了一个思维导图,以了解此脚本将要做什么。基于这种思维导图,我想到了将代码拆分到不同文件中的想法,以便更好地组织所有内容并简化调试过程。所以,我做到了。我将凭据(用于api)存储在一个文件中,将大型机存储在另一个文件中,将功能存储在另一个文件中。我使用From Credentials import *From Comands import *将文件导入大型机。当有任何文本输入到bot时,它首先检查其启动方式,如果以“ /”开头,则将斜杠后的内容存储在变量中,并将其作为参数发送到功能文件。什么时候开始寻找所需的确切命令并执行它。它有效,但我想是否有更好的方法可以做到这一点。希望我能很好地解释问题,并且您可以帮助我。这是我在说的代码摘录。

mainframe.py

from Comands import *
from credentials import *

...

if text.startswith("/"):
            comando = text[1:]
            print(comando)
            Comands.search(comando)
elif text in items:
            db.delete_item(text, chat)
            items = db.get_items(chat)
            keyboard = build_keyboard(items)
            send_message("Select an item to delete", chat, keyboard)
else:
            db.add_item(text, chat)
            items = db.get_items(chat)
            message = "\n".join(items)
            send_message(message, chat)
...

Comands.py

from message_dictionary import *
from mainframe import *

def search(comando):
    if comando == "start":
        def start():
            keyboard = build_keyboard(acuerdo)
            send_message(mensaje["start"], chat, keyboard)
    elif comando == "done":
        def done():
            keyboard = build_kerboard(items)
            send_message("Select an item to delete", chat, keyboard)

2 个答案:

答案 0 :(得分:0)

首先,我将从2条建议开始:

  • 不要在导入文件中使用星号(很难说出以后在哪里声明函数)
  • 尝试避免循环导入(在mainframe.py中导入Command,在command.py中导入主机)

mainframe.py

import command

comando_str = 'str_command'

# at this stage we want to call command.str_command(), but we have a string, not a function
if hasattr(command, comando_str):  # let's check if such command exist in `command` module
    comando_function = getattr(command, comando_str)  # now let's get a reference to that function

    # we can now call comando_function()!
    # but maybe you have some parameters to call (like passing in `keyboard`)
    arg_count = comando_function.__code__.co_argcount  # total number of arguments to the function
    # co_varnames has all the variables that function would use, but arguments come firs
    arg_names = comando_function.__code__.co_varnames[:arg_count]  

    if arg_count >= 1 and arg_names[0] == 'keyboard':
         comando_function(keyboard)
    elif arg_count == 0:  # function require no arguments
         comando_function()
    else:
        raise Exception('Function %s could not be called', comando_str)
else:
    raise Exception('Function command.%s is not declared', comando_str)

command.py

import message_dictionary as md  # no *!

def str_command(keyboard):
    md.send_message(mensaje["start"], chat, keyboard)  # now I know that send_message is in md (message_dictionary)

def start():
    keyboard = build_keyboard(acuerdo)  
    send_message(mensaje["start"], chat, keyboard)  

关于comand.py的一些说明:

def search(comando):  # ok
    if comando == "start":  # ok
        # here you define function `start`
        # yet, you have not called `start` function 
        # so, when you exit `search` function, this function is gone!
        def start():
            keyboard = build_keyboard(acuerdo)  # where is acuerdo is declared?
            send_message(mensaje["start"], chat, keyboard)  # where mensaje and chat are declared?
    elif comando == "done":
        # same problem as with `start` function above
        def done():
            keyboard = build_kerboard(items)
            send_message("Select an item to delete", chat, keyboard)

修改了comand.py以返回可调用函数(以解决注释中的问题):

def search(comando): 
    if comando == "start":
        def start(): 
            keyboard = build_keyboard(acuerdo)  
            send_message(mensaje["start"], chat, keyboard)  
        return start
    elif comando == "done":
        # same problem as with `start` function above
        def done():
            keyboard = build_kerboard(items)
            send_message("Select an item to delete", chat, keyboard)
        return done

修改片段mainframe.py以使用返回值:

if text.startswith("/"):
    comando = text[1:]
    print(comando)  # look at the logging as a fancy replacing for print
    call_me = Comands.search(comando)
    if call_me:  # checking that something is returned (not None)
        call_me()  # example of calling it

答案 1 :(得分:0)

是的。

mainframe.py(实际上称为Prubeas.py)

#PYTHON 3.6.2
#LGsus

import json
import requests
import time
import urllib
from dbhelper import DBHelper
from credentials import *
from message_dictionary import *
import Comands

db = DBHelper()

#DECLARAR ID DEL BOT Y URL DE TELEGRAM
URL = "https://api.telegram.org/bot{}/".format(telegram_token)

#CONSULTAR ESTADO
def get_url(url):
    response = requests.get(url)
    content = response.content.decode("utf8")
    return content

#CAMBIAR DE JSON A PYTHON (PARSE)
def get_json_from_url(url):
    content = get_url(url)
    js = json.loads(content)
    return js

#SOLICITAR LISTA DE MENSAJES
def get_updates(offset=None):
    url = URL + "getUpdates?timeout=100"
    if offset:
        url += "&offset={}".format(offset)
    js = get_json_from_url(url)
    return js

#DETERMINAR MENSAJES NO  LEÍDOS
def get_last_update_id(updates):
    update_ids = []
    for update in updates["result"]:
        update_ids.append(int(update["update_id"]))
    return max(update_ids)

#RESPONDER A TODOS LOS NO LEIDOS
def handle_updates(updates):
    for update in updates["result"]:
        text = update["message"]["text"]
        chat = update["message"]["chat"]["id"]
        items = db.get_items(chat)
        if text.startswith("/"):
            comando = text[1:]
            print(comando)
            Comands.search(comando)
            #fin = text.find(" ")
            #print(fin)

            #if text == "/done":
            #    keyboard = build_keyboard(items)
            #    send_message("select an item to delete", chat, keyboard)
            #elif text == "/start":
            #    keyboard = build_keyboard(acuerdo)
            #    send_message(mensajes["start"], chat, keyboard)
            #elif text.startswith("/"):
            #    continue
        elif text in items:
            db.delete_item(text, chat)
            items = db.get_items(chat)
            keyboard = build_keyboard(items)
            send_message("Select an item to delete", chat, keyboard)
        else:
            db.add_item(text, chat)
            items = db.get_items(chat)
            message = "\n".join(items)
            send_message(message, chat)

#SOLICITAR ULTIMO MENSAJE Y ID DEL CHAT
def get_last_chat_id_and_text(updates):
    global Texto
    global full_last
    num_updates = len(updates["result"])
    lista = updates["result"]
    data = json.dumps(lista)
    last_update = num_updates - 1
    full_last = updates["result"][last_update]
    Texto = "text" in full_last["message"]
    if Texto == True:
        text = updates["result"][last_update]["message"]["text"]
    else:
        text = "Entrada invalida"
    chat_id = updates["result"][last_update]["message"]["chat"]["id"]
    return (text, chat_id)

#CREAR EL TECLADO
def build_keyboard(items):
    keyboard = [[item] for item in items]
    reply_markup = {"keyboard":keyboard, "one_time_keyboard":True}
    return json.dumps(reply_markup)

#ENVIAR MENSAJE
def send_message(text, chat_id, reply_markup=None):
    text = text.encode(encoding='utf-8')
    text = urllib.parse.quote_plus(text)
    url = URL + "sendMessage?text={}&chat_id={}&parse_mode=Markdown".format(text, chat_id)
    if reply_markup:
        url += "&reply_markup={}".format(reply_markup)
    get_url(url)
    print (text)

text, chat = get_last_chat_id_and_text(get_updates())
send_message(text, chat)

##EJECUTAR
def main():
    db.setup()
    last_update_id = None
    while True:
        updates = get_updates(last_update_id)
        if len(updates["result"]) > 0:
            last_update_id = get_last_update_id(updates) + 1
            handle_updates(updates)
        time.sleep(0.5)

#CONDICION PARA EJECUTAR
if __name__ == '__main__':
    main()





#import ccxt

#b = ccxt.bitso({
#    'apiKey': "XXXXXX",
#    'secret': "XXXXXX",
#    'verbose': False,
#    })
#
#print(b.fetchBalance())

此代码末尾注释的是某个API,一旦完成电报api,我将在稍后尝试使用。

Comands.py

#Lista de comandos

from message_dictionary import *
from Prubebas import *

def search(comando):
    if comando == "start":

    #def start():
        keyboard = build_keyboard(acuerdo)
        send_message(mensaje["start"], chat, keyboard)

    def done():
        keyboard = build_kerboard(items)
        send_message("Select an item to delete", chat, keyboard)

我很抱歉混合语言。非常感谢您的帮助。