Как прочитать файл, содержащий вопросы и ответы для теста, сохраненного в виде строкового представления списка? - PullRequest
0 голосов
/ 05 января 2019

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

Я пытался использовать strip, чтобы убрать строку появляющихся кавычек, но я получаю сообщение об ошибке

У объекта "list" нет атрибута "strip"

Я относительно новичок в Python, поэтому я изо всех сил пытаюсь найти другие исправления, я попытался выделить печать в другой строке, а затем поместить ее в список, но в итоге он сказал, что список снова не вызывается .

textquestions=open('listofquestions','r')

allthequestions = textquestions.readlines()

forbuttons=[print(allthequestions)]

textquestions.close

q1 = forbuttons(0)

buttonq1 = tk.Button(self, text=forbuttons[q1][0])
buttonq1.pack()

В файле записано это и больше ничего (вопросы о наполнителе, чтобы заставить его работать в первую очередь):

["What would you wear to work?","Hoodie", "Suit", "Shorts","2"],["How would you greet a customer?","Hey", "Hi", "Hello", "0"],["How many years of experience do you have?","Loads", "None", "Some","1"],["Why do you want to work here?","It's fun", "No money", "Friend told me to","2"]

Тем не менее, когда они печатаются, они, кажется, печатают так:

'["What would you wear to work?","Hoodie", "Suit", "Shorts","2"],["How would you greet a customer?","Hey", "Hi", "Hello", "0"],["How many years of experience do you have?","Loads", "None", "Some","1"],["Why do you want to work here?","It's fun", "No money", "Friend told me to","2"]'

И я думаю, что цитаты вокруг всего этого мешают списку работать? Хотя я не уверен, может быть, остальная часть кода тоже не права.

Ответы [ 3 ]

0 голосов
/ 05 января 2019

Ошибка

У объекта "list" нет атрибута "strip"

появляется, потому что - как говорит ошибка - вы пытались вызвать метод strip для объекта типа list. Полагаю, вы хотели позвонить strip на string внутри списка. В любом случае, strip не поможет вам с вашей проблемой, я думаю.

В общем: Возможно, вам следует изменить способ сохранения данных вопросов.


Однако, как говорится, вы все равно можете загрузить данные с помощью:

import yaml

with open('listofquestions') as f:
    data = f.read()
    questions = yaml.safe_load('[{}]'.format(data))

В результате содержимое вашего файла можно интерпретировать как частичный файл YAML - единственное, чего не хватает, - это открывающая скобка [ и закрывающая скобка ]. Мы можем добавить их к содержимому после прочтения файла и впоследствии проанализировать содержимое YAML.

Улучшения:

Первый вопрос в questions[0][0], три ответа в questions[0][1], questions[0][2] и questions[0][3] и правильное решение в questions[0][4].

Вы можете получить доступ к этим значениям, чтобы построить графический интерфейс, подобный следующему:

screenshot

import tkinter as tk
root = tk.Tk()
label_question = tk.Label(root, text=questions[0][0])
label_question.pack(side=tk.TOP)
button_answer_1 = tk.Button(root, text=questions[0][1])
button_answer_1.pack(side=tk.LEFT)
button_answer_2 = tk.Button(root, text=questions[0][2])
button_answer_2.pack(side=tk.LEFT)
button_answer_3 = tk.Button(root, text=questions[0][3])
button_answer_3.pack(side=tk.LEFT)
root.mainloop()
0 голосов
/ 05 января 2019

Есть несколько проблем с вашим подходом, некоторые ошибки кодирования, некоторые концептуальные.

Проблема с понятием:

Как я заметил, основная проблема заключается в том, что вы, кажется, думаете, что помещение некоторого текста в файл, представляющий собой последовательность разделенных запятыми квадратных скобок, заключенных в двойные кавычки, приведет к созданию списка в вашем Python. программа при чтении с использованием дескриптора файла с readlines().

Более того, когда вы жаловались на напечатанную заключенную в одинарные кавычки строку, вы, похоже, ожидали, что прочитанное из файла будет напечатано в виде отдельных квадратных скобок (возможно, каждый в одной строке?) вместо одной строки.

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

Когда вы open() файл и затем вызываете readlines() для дескриптора файла, это не интерпретатор Python, который читает файл. На самом деле, на низком уровне, это ядро, которое читает файл кусками соответствующего размера и помещает его в память, а именно в часть памяти, к которой относится ваша переменная allthequestions. Подумайте об этом: если бы первая теория была верной, то использование readlines() для файла фактически выполняло бы все, что было похоже на команду Python. Тогда как бы он вообще знал, что вернуть? Возможно, результат последнего выражения? Список всех результатов выражения в файле? Кортеж из них? Независимо от того, как мы смотрим на это, было бы трудно определить, каково даже ваше ожидаемое поведение для readlines(). С такими вещами лучше всего экспериментировать на отдельных небольших примерах, прежде чем использовать их в полной программе.

Кроме того, как следует из названия, readlines() читает текст как строки , а не как разделенные запятыми списки Python или любые другие токены. Результатом, хотя и не списком, является итеративная коллекция всех строк в файле. Это означает, что в вашем случае - в соответствии с тем, что вы написали - это одна строка, содержащая:

["What would you wear to work?","Hoodie", "Suit", "Shorts","2"],["How would you greet a customer?","Hey", "Hi", "Hello", "0"],["How many years of experience do you have?","Loads", "None", "Some","1"],["Why do you want to work here?","It's fun", "No money", "Friend told me to","2"]

, включая перевод строки в конце.

Проверяя эту структуру данных, кажется, что вы хотите проанализировать одну последовательность последовательностей из файла, где каждая вложенная последовательность содержит текстовые элементы. Первый (или, другими словами, 0-й) элемент каждой вложенной последовательности является вопросом, тогда как любой другой текстовый элемент является возможным ответом на этот вопрос. Что означает число в последнем элементе, я не смог расшифровать.

Решения:

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

Если вы хотите обрабатывать ваши данные только на Python, я бы предложил метод сериализации , например, модуль pickle. Этот модуль позволяет записывать объект python в файл в таком формате, чтобы его можно было снова прочитать в переменную (конечно, НЕ с readlines(), который предназначен для чтения строк, а не объектов).

Чтобы продемонстрировать, как это работает в конце записи и чтения, вот несколько фрагментов кода:

Пример для пишущего компонента:

# write_questions.py
import pickle

all_the_questions = (["What would you wear to work?","Hoodie", "Suit",     "Shorts","2"],["How would you greet a customer?","Hey", "Hi", "Hello", "0"],["How     many years of experience do you have?","Loads", "None", "Some","1"],["Why do you     want to work here?","It's fun", "No money", "Friend told me to","2"])

questions_file = open("questions.dmp", "w")
pickle.dump(all_the_questions, questions_file)

questions_file.close()

Пример для компонента чтения:

# read_questions.py
import pickle

questions_file = open("questions.dmp")

all_the_questions = pickle.load(questions_file)

print(all_the_questions[0])
print(all_the_questions[1])

Структура данных all_the_questions представляла собой кортеж из списков строк, который был выгружен в файл "questions.dmp" с использованием pickle.dump(). Обратите внимание, что созданный файл "questions.dmp" содержит специальную запись объекта, которая используется pickle для считывания его содержимого обратно в качестве переменной и не читается человеком!

Как только вы запустите часть чтения, вы увидите, что индексирование по переменной all_the_questions работало правильно после того, как переменная была создана из содержимого файла с использованием pickle.load(), и вы получили что-то вроде этого, записанное в ваш терминал:

['What would you wear to work?', 'Hoodie', 'Suit', 'Shorts', '2']
['How would you greet a customer?', 'Hey', 'Hi', 'Hello', '0']

Другим решением было бы использование стандартного формата текстовых данных, например CSV (значения, разделенные запятыми), для которого в стандартной библиотеке Python есть анализаторы. По сути, вы можете хранить каждый список вопросов в виде отдельной строки в файле «questions.csv», не разделяя его символами [], и каждая строка может занимать позицию между запятыми в строке вопроса, например:

What would you wear to work?,Hoodie, Suit, Shorts,2
How would you greet a customer?,Hey, Hi, Hello, 0
How many years of experience do you have?,Loads, None, Some,1
Why do you want to work here?,It's fun, No money, Friend told me to,2

Ответ уже слишком длинный, поэтому я предоставляю читателю интерес к использованию анализа CSV, чтобы посмотреть, как он работает. Есть несколько доступных ресурсов, так же как для маринада. Преимущества состоят в том, что данные, хранящиеся в файле, будут удобочитаемыми, и их обработка не будет ограничена программами Python, поскольку CSV - довольно часто используемый старый формат.

Проблемы с кодированием:

Предыдущий раздел уже касался части кода, касающейся readlines(), но есть еще некоторые проблемы.

Во-первых:

forbuttons=[print(allthequestions)]

Эта строка печатает текстовое представление объекта коллекции, хранящегося в allthequestions, преобразует возвращаемое значение print в список и связывает полученное значение с forbuttons. Поскольку print() всегда возвращает значение None, значение forbuttons будет одноэлементным списком, содержащим только None. Напечатано, это будет выглядеть примерно так:

[None]

Далее

textquestions.close

строка на самом деле не вызывает функцию close() для дескриптора файла, она только оценивает объект функции , ничего не делая.

Затем исходный фрагмент пытается вызвать объект в forbuttons с аргументом 0, как если бы это была функция. Увы, это не так, это список [None], как объяснено выше:

q1 = forbuttons(0)

Впоследствии вы вдруг решаете трактовать forbuttons как индексируемый список вместо функции, многомерного!

buttonq1 = tk.Button(self, text=forbuttons[q1][0])

Если честно, я действительно понятия не имею, что это даст вам, поэтому я не могу предложить альтернативу. Возможно, вы хотели сделать что-то вроде:

buttonq1 = tk.Button(self, text=allthequestions[0][0])

, где текст кнопки будет установлен на самый первый вопрос, если бы вы использовали, например, рассол вместо readlines().

Другая проблема, которую я нахожу в вашем представлении данных, заключается в том, что вы в основном используете магические числа, такие как 0, чтобы запомнить, где находится фактическая часть вопроса в списке вопросов. Может быть, использовать словарь, где ключ является фактической строкой вопроса, и значение возможных ответов будет лучше. В этом случае структура одного вопроса будет выглядеть так:

{ "What would you wear to work?" : ["Hoodie", "Suit", "Shorts","2"] }

Соглашение об именах также причудливо по нескольким причинам:

Во-первых, неоднозначно, что к чему. Является ли «вопрос» целой структурой данных, которая включает в себя строку вопроса, как это было бы задано человеком, а также возможные ответы? Или это просто строка вопроса?

Второе: переменные в общем случае не соответствуют каким-либо нормальным правилам именования. Обычные соглашения об именах включают «camelCase», «PascalCase» (или верхний регистр верблюда), «snake_case» и т. Д. Руководство по стилю Python, PEP-8, рекомендует использовать «snake_case» для переменных и функций, «UPPER_SNAKE_CASE» для переменных, которые должны быть постоянными, и «PascalCase» для имен типов.

приписка

В общем, прежде чем применять их, особенно вместе, нужно всегда изучать и знать, что / что делает каждая концепция, функция и т. Д. Это требует большой практики и экспериментов, а также изучения документации.

Если честно, первоначальный вопрос совсем не выглядит так, будто в него было вложено много исследований или работ. Несмотря на это, мне это не понравилось, так как оригинальный постер был новым автором и, как кажется, довольно новым для программирования.

0 голосов
/ 05 января 2019

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

Один очень простой способ сделать это - добавить [ и ] и обработать его как JSON структура:

import json

with open('listofquestions') as textquestions:
    questions_json = '[' + textquestions.read() + ']'
    allthequestions = json.loads(questions_json)

Python 'eval функция также будет работать, но она может создать уязвимости безопасности, если входные данные ненадежны (в них будет выполнен произвольный код).

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