1

I want to contruct an exam paper in latex. I need a question library written in latex. For example, there are 10 questions in it. A latex code is required that randomly selects 3 of these 10 questions, creates an exam paper and adds the answer sheet at the end. I have the following code:

\documentclass[a4paper,12pt]{exam}
\usepackage[utf8]{inputenc}
\usepackage{amsmath}
\usepackage{enumitem}
\usepackage{pythontex}

\begin{document}
    
    \title{Exam}
    \author{ }
    \date{\today}
    
    \maketitle
    
    \section*{Sorular}
    
    
    \begin{pycode}
        import random
        
        # Rastgele 3 soru seç
        selected_questions = random.sample(range(1, 11), 3)
    \end{pycode}
    
    \begin{questions}
        % Seçilen soruları çağır
        \pyc{for q in selected_questions:}%
        \pyc{    print("\\question" + str(q))}%
    \end{questions}
    
    \newpage
    \section*{Cevap Anahtarı}
    
    \begin{questions}
        \question[1] b % Soru 1 için doğru cevap
        \question[2] b % Soru 2 için doğru cevap
        \question[3] b % Soru 3 için doğru cevap
        \question[4] c % Soru 4 için doğru cevap
        \question[5] b % Soru 5 için doğru cevap
        \question[6] a % Soru 6 için doğru cevap
        \question[7] a % Soru 7 için doğru cevap
        \question[8] b % Soru 8 için doğru cevap
        \question[9] b % Soru 9 için doğru cevap
        \question[10] d % Soru 10 için doğru cevap
    \end{questions}
    
\end{document}

when it runs, I get the error as Something's wrong--perhaps a missing \item. \end{questions}

I could not solve it. Could you solve it?

1 Answer 1

0

The issue is that \begin{questions} starts a list environment, and there must be at least one item present. The same problem would appear with the normal LaTeX

\begin{itemize}
\end{itemize}

without any \item in between.

The python code will insert the required \question commands, but only during the second run after first running LaTeX once (to collect the python code) and then PythonTeX (to run the python code and prepare the output to be used by LaTeX). So during the first run you will get the error.

There are two solutions: the first is to ignore the error during the first run (by pressing Enter when the error is shown or by compiling in batchmode or nonstopmode) which will allow to run PythonTeX and a successful second LaTeX run, or to include some code that will check if it is the first run, and if so, to insert a dummy question to avoid the error message.

An easy way is to define a dummy command in the python code, and check in LaTeX if this command is defined using \ifcsname. If it is defined then PythonTeX has run and the dummy question is not needed. If it is not defined then the dummy question can be used.

The command should be defined globally (with \gdef) otherwise it is only defined within the pycode environment.

MWE (with the Python code changed a bit to avoid indentation errors):

\documentclass[a4paper,12pt]{exam}
\usepackage[T1]{fontenc}
\usepackage{amsmath}
\usepackage{enumitem}
\usepackage{pythontex}

\begin{document}
    
    \title{Exam}
    \author{ }
    \date{\today}
    
    \maketitle
    
    \section*{Sorular}
    
    
    \begin{pycode}
import random

# Rastgele 3 soru seç
selected_questions = random.sample(range(1, 11), 3)
print("\\gdef\\hasrun{yes}")
    \end{pycode}
    
    \begin{questions}
        \ifcsname hasrun\endcsname\else\question dummy question\fi%
        % Seçilen soruları çağır
        \begin{pycode}
for q in selected_questions:
    print("\\question" + str(q))
        \end{pycode}
    \end{questions}
    
    \newpage
    \section*{Cevap Anahtarı}
    
    \begin{questions}
        \question[1] b % Soru 1 için doğru cevap
        \question[2] b % Soru 2 için doğru cevap
        \question[3] b % Soru 3 için doğru cevap
        \question[4] c % Soru 4 için doğru cevap
        \question[5] b % Soru 5 için doğru cevap
        \question[6] a % Soru 6 için doğru cevap
        \question[7] a % Soru 7 için doğru cevap
        \question[8] b % Soru 8 için doğru cevap
        \question[9] b % Soru 9 için doğru cevap
        \question[10] d % Soru 10 için doğru cevap
    \end{questions}
    
    \begin{itemize}
    \end{itemize}
    
\end{document}

Result after first LaTeX run:

enter image description here

Result after PythonTeX run and second LaTeX run:

enter image description here

Note that this may not always work, if the second python block does not produce the correct code for the questions but the first block has run then the command will be defined but still the error will be triggered. To be able to correct the python code you can delete the files generated by PythonTeX, correct the code, and run again (as also described in the PythonTeX documentation).

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .