Error too few arguments for format

Ответили на вопрос 1 человек. Оцените лучшие ответы! И подпишитесь на вопрос, чтобы узнавать о появлении новых ответов.

Пытаюсь сделать insert данных в БД.

sql = "insert into items (`resource_id`,`item_link`,`item_title`,`item_datetime`,`item_text_content`) values (%s,%s,%s,%s,%s)"
          cursor.execute(sql, (str(resource_id), (str(item_link), str(item_title), str(item_datetime), str(item_content))))

Выходит такая ошибка:

Traceback (most recent call last):
  File "C:/PycharmProjects/parser_goose_and_boilerpipe.py", line 83, in <module>
    call_all_func(resources)
  File "C:/PycharmProjects/parser_goose_and_boilerpipe.py", line 79, in call_all_func
    cursor.execute(sql, (str(resource_id), (str(item_link), str(item_title), str(item_datetime), str(item_content))))
  File "C:AppDataLocalProgramsPythonPython37-32libsite-packagespymysqlcursors.py", line 168, in execute
    query = self.mogrify(query, args)
  File "AppDataLocalProgramsPythonPython37-32libsite-packagespymysqlcursors.py", line 147, in mogrify
    query = query % self._escape_args(args, conn)
TypeError: not enough arguments for format string

Process finished with exit code 1

Cудя по traceback мне понятно что у меня недостаточно аргументов для форматирования.Но вроде 5 у меня аргументов и все они 5 аргументов вроде переданы.
P.S: Раньше этот кусок кода был таким

sql = "insert into items (`item_link`,`item_title`,`item_datetime`,`item_text_content`) values (%s,%s,%s,%s)"
          cursor.execute(sql,  (str(item_link), str(item_title), str(item_datetime), str(item_content)))

И все работало нормально.

UPD:Исправил код таким образом:

sql = "insert into items (`resource_id`,`item_link`,`item_title`,`item_datetime`,`item_text_content`) values (%s,%s)"
                    cursor.execute(sql, (str(resource_id), (str(item_link), str(item_title), str(item_datetime), str(item_content))))

Теперь ошибка такая:

Traceback (most recent call last):
  File "C:PycharmProjects/parser_russian_resource/parser_goose_and_boilerpipe.py", line 83, in <module>
    call_all_func(resources)
  File "C:PycharmProjects/parser_russian_resource/parser_goose_and_boilerpipe.py", line 79, in call_all_func
    cursor.execute(sql, (str(resource_id), (str(item_link), str(item_title), str(item_datetime), str(item_content))))
  File "C:AppDataLocalProgramsPythonPython37-32libsite-packagespymysqlcursors.py", line 170, in execute
    result = self._query(query)
  File "C:AppDataLocalProgramsPythonPython37-32libsite-packagespymysqlcursors.py", line 328, in _query
    conn.query(q)
  File "C:AppDataLocalProgramsPythonPython37-32libsite-packagespymysqlconnections.py", line 517, in query
    self._affected_rows = self._read_query_result(unbuffered=unbuffered)
  File "C:AppDataLocalProgramsPythonPython37-32libsite-packagespymysqlconnections.py", line 732, in _read_query_result
    result.read()
  File "C:AppDataLocalProgramsPythonPython37-32libsite-packagespymysqlconnections.py", line 1075, in read
    first_packet = self.connection._read_packet()
  File "C:AppDataLocalProgramsPythonPython37-32libsite-packagespymysqlconnections.py", line 684, in _read_packet
    packet.check_error()
  File "C:AppDataLocalProgramsPythonPython37-32libsite-packagespymysqlprotocol.py", line 220, in check_error
    err.raise_mysql_exception(self._data)
  File "C:AppDataLocalProgramsPythonPython37-32libsite-packagespymysqlerr.py", line 109, in raise_mysql_exception
    raise errorclass(errno, errval)
pymysql.err.InternalError: (1136, "Column count doesn't match value count at row 1")

Process finished with exit code 1

И уже эта ошибка говорит мне что количество столбцов не соответствует значению в строке.
Возможно ли эта ошибка из-за того что у меня в VALUES только два %s %s ? значения?

UPD1: Если я передам больше 2 то код опять выдает эту ошибку TypeError: not enough arguments for format string

Inspired by this open ticket on Boost, this seeks to complete the work there.

Given a printf-style format string and associated arguments, a static_assert is performed on whether the format string and arguments are valid.

I’m particularly interested in:

  • Have I covered all possible format strings?
  • Am I doing this in the most efficient way?

This includes changes based on the comments from @Loki Astari on the previous iteration of this code here.

Here is the below code running on ideone.

#include <cstddef>
#include <cstdio>
#include <stdexcept>
#include <boost/utility/string_ref.hpp>
#include <boost/format.hpp>

#ifndef BOOST_PP_VARIADICS
#    define BOOST_PP_VARIADICS
#endif
#include <boost/preprocessor.hpp>

template<typename... Ts>
struct Format
{
    template<std::size_t N>
    static constexpr bool check(const char (&fmt)[N], std::size_t n);
};

//////////////////////

template<std::size_t N>
constexpr bool checkValidFormats(const char (&fmt)[N], size_t n, char c)
{
    return n >= N ?
            throw std::logic_error("invalid format for type")
        : fmt[n] == c ?
            true
        : checkValidFormats(fmt, n + 1, c);
}

template<class>
struct Type;

#define SUPPORTED_TYPE(T, Fmts) 
template<> 
struct Type<T> 
{ 
    template<std::size_t N> 
    constexpr static bool check(const char (&fmt)[N], std::size_t n) 
    { 
        return n >= N ? 
                throw std::logic_error("invalid format for type") 
            : checkValidFormats(Fmts, 0, fmt[n]); 
    } 
}

SUPPORTED_TYPE(char,              "c");
SUPPORTED_TYPE(int8_t,            "cd");
SUPPORTED_TYPE(uint8_t,           "cu");
SUPPORTED_TYPE(int16_t,           "d");
SUPPORTED_TYPE(uint16_t,          "u");
SUPPORTED_TYPE(int32_t,           "d");
SUPPORTED_TYPE(uint32_t,          "u");
SUPPORTED_TYPE(char*,             "s");
SUPPORTED_TYPE(unsigned char*,    "s");
SUPPORTED_TYPE(const char*,       "s");
SUPPORTED_TYPE(std::string,       "s");
SUPPORTED_TYPE(boost::string_ref, "s");
SUPPORTED_TYPE(double,            "f");
SUPPORTED_TYPE(float,             "f");

#define SUPPORTED_LL_TYPE(T, C) 
template<> 
struct Type<T> 
{ 
    template<std::size_t N> 
    static constexpr bool check(const char (&fmt)[N], std::size_t n) 
    { 
        return n < N && 
               n - 2 >= 0 && 
               fmt[n]     == C   && 
               fmt[n - 1] == 'l' && 
               fmt[n - 2] == 'l' ? 
                    true 
            : throw std::logic_error("invalid format for type"); 
    } 
}

SUPPORTED_LL_TYPE(int64_t,  'd');
SUPPORTED_LL_TYPE(uint64_t, 'u');

template<typename... Ts>
struct Argument
{
    template<std::size_t N>
    static constexpr bool check(const char (&)[N], std::size_t)
    {
        return false;
    }
};

template<typename T, typename... Ts>
struct Argument<T, Ts...>
{
    template<std::size_t N>
    static constexpr bool check(const char (&fmt)[N], std::size_t n)
    {
        //    %[<flags>][<width>][.<precision>][<length>]<specifier>
        //        specifier := d|i|u|o|x|X|f|F|e|E|g|G|a|A|c|s|p|n
        return Type< typename std::decay<T>::type>::check(fmt, n) &&
                Format<Ts...>::check(fmt, n + 1);
    }
};

///////////////////////////

template<size_t N>
constexpr bool isDoubleLengthSpecifier(const char (&fmt)[N], std::size_t n)
{
    // hh | ll
    return n + 2 < N &&
           ((fmt[n] == 'h' && fmt[n + 1] == 'h') ||
            (fmt[n] == 'l' && fmt[n + 1] == 'l'));
}

template<size_t N>
constexpr bool isSingleLengthSpecifier(const char (&fmt)[N], std::size_t n)
{
    // h | l | j | z | t | L
    return n + 1 < N &&
           (fmt[n] == 'h' ||
            fmt[n] == 'l' ||
            fmt[n] == 'j' ||
            fmt[n] == 'z' ||
            fmt[n] == 't' ||
            fmt[n] == 'L');
}

template<size_t N>
constexpr size_t nextNonLengthSpecifier(const char (&fmt)[N], std::size_t n)
{
    return
            isDoubleLengthSpecifier(fmt, n) ? n + 2
          : isSingleLengthSpecifier(fmt, n) ? n + 1
          : n;
}

template<typename... Ts>
struct Length
{
    template<std::size_t N>
    static constexpr bool check(const char (&)[N], std::size_t)
    {
        return false;
    }
};

template<typename T, typename... Ts>
struct Length<T, Ts...>
{
    template<std::size_t N>
    static constexpr bool check(const char (&fmt)[N], std::size_t n)
    {
        //    %[<flags>][<width>][.<precision>][<length>]<specifier>
        //        length    := hh|h|l|ll|j|z|t|L
        return Argument<T, Ts...>::check(fmt, nextNonLengthSpecifier(fmt, n));
    }
};

///////////////////////////

template<std::size_t N>
constexpr size_t nextNonLiteralPrecision(const char (&fmt)[N], std::size_t n)
{
    return
        n >= N ?
            throw std::logic_error("invalid format string - parsing precision")
        : fmt[n] >= '0' && fmt[n] <= '9' ?
                nextNonLiteralPrecision(fmt, n + 1)
        : n;
}

template<typename... Ts>
struct Precision
{
    template<std::size_t N>
    static constexpr bool check(const char (&)[N], std::size_t)
    {
        return false;
    }
};

template<typename T, typename... Ts>
struct Precision<T, Ts...>
{
    template<std::size_t N>
    static constexpr bool check(const char (&fmt)[N], std::size_t n)
    {
        //    %[<flags>][<width>][.<precision>][<length>]<specifier>
        //        precision := <number>|'*'        // A number or a '*'

        // if precision is a provided argument, validate it is integral
        return n + 1 < N && fmt[n] == '.' && fmt[n + 1] == '*' ?
                std::is_integral<T>::value && Length<Ts...>::check(fmt, n + 2)

        // otherwise skip over any literal precision
        : n + 1 < N && fmt[n] == '.' ?
                Length<T, Ts...>::check(fmt, nextNonLiteralPrecision(fmt, n + 1))

        : Length<T, Ts...>::check(fmt, n);
    }
};

///////////////////////////

template<std::size_t N>
constexpr size_t nextNonLiteralWidth(const char (&fmt)[N], std::size_t n)
{
    return
        n >= N ?
            throw std::logic_error("invalid format string - parsing width")
        : fmt[n] >= '0' && fmt[n] <= '9' ?
            nextNonLiteralWidth(fmt, n + 1)
        : n;
}

template<typename... Ts>
struct Width
{
    template<std::size_t N>
    static constexpr bool check(const char (&)[N], std::size_t)
    {
        return false;
    }
};

template<typename T, typename... Ts>
struct Width<T, Ts...>
{
    template<std::size_t N>
    static constexpr bool check(const char (&fmt)[N], std::size_t n)
    {
        //    %[<flags>][<width>][.<precision>][<length>]<specifier>
        //        width     := <number>|'*'        // A number or a '*'

        // if width is a provided argument, validate it is integral
        return fmt[n] == '*' ?
                std::is_integral<T>::value && Precision<Ts...>::check(fmt, n + 1)

        // otherwise skip over any literal width
        : Precision<T, Ts...>::check(fmt, nextNonLiteralWidth(fmt, n));
    }
};

///////////////////////////

template<size_t N>
constexpr bool isFlag(const char (&fmt)[N], std::size_t n)
{
    return n + 1 < N &&
          (fmt[n] == '-' ||
           fmt[n] == '+' ||
           fmt[n] == ' ' ||
           fmt[n] == '#' ||
           fmt[n] == '0');
}

template<std::size_t N>
constexpr size_t nextNonFlag(const char (&fmt)[N], std::size_t n)
{
    return
        n >= N ?
            throw std::logic_error("invalid format string")
        : isFlag(fmt, n) ?
            nextNonFlag(fmt, n + 1)
        : n;
}

template<typename T, typename... Ts>
struct Flags
{
    template<std::size_t N>
    static constexpr bool check(const char (&fmt)[N], std::size_t n)
    {
        //    %[<flags>][<width>][.<precision>][<length>]<specifier>
        //        flags     := [-+ #0]*            // Zero or more
        return Width<T, Ts...>::check(fmt, nextNonFlag(fmt, n));
    }
};

///////////////////////////

template<size_t N>
constexpr bool isLiteralPercent(const char (&fmt)[N], std::size_t n)
{
    return n + 1 <= N && fmt[n] == '%' && fmt[n + 1] == '%';
}

template<typename T, typename... Ts>
struct Format<T, Ts...>
{
    template<std::size_t N>
    static constexpr bool check(const char (&fmt)[N], std::size_t n)
    {
        return
            n >= N ?
                throw std::logic_error("too many arguments for provided format string")

            // skip non-format specifiers (ie: not a % character)
            : fmt[n] != '%' ?
                Format<T, Ts...>::check(fmt, n + 1)

            // %%
            : isLiteralPercent(fmt, n) ?
                Format<T, Ts...>::check(fmt, n + 2)

            // we've found a format specifier
            : Flags<T, Ts...>::check(fmt, n + 1);
    }
};

template<>
struct Format<>
{
    template<std::size_t N>
    static constexpr bool check(const char (&fmt)[N], std::size_t n)
    {
        return
            n>= N ?
                true
            : fmt[n] != '%' ?
                check(fmt, n + 1)
            : fmt[n + 1] == '%' ?
                check(fmt, n + 2)
            : throw std::logic_error("too few arguments for provided format string");
    }
};

////////////////

// printing...

void add(boost::format&)
{ }

template<typename T, typename... Ts>
void add(boost::format& f, const T& arg, const Ts&... ts)
{
    f % arg;
    add(f, ts...);
}

////////////////

#define PP_PARENTHESISE_WITH_TOKEN(r, token, i, e) 
    BOOST_PP_COMMA_IF(i) token(e)

#define PP_CSV_SEQ_PARENTHESISE_WITH_TOKEN(...) 
    BOOST_PP_SEQ_FOR_EACH_I(PP_PARENTHESISE_WITH_TOKEN, decltype, BOOST_PP_VARIADIC_TO_SEQ(__VA_ARGS__))

#define PP_PERFORM_LOG_FORMAT_CHECK(fmt, ...) 
    Format<BOOST_PP_IF(BOOST_PP_EQUAL(BOOST_PP_TUPLE_SIZE((,##__VA_ARGS__)), 1), 
            BOOST_PP_EXPAND, PP_CSV_SEQ_PARENTHESISE_WITH_TOKEN)(__VA_ARGS__)>::check(fmt, 0)

#define LOG(fmt, ...) 
    { 
        static_assert(PP_PERFORM_LOG_FORMAT_CHECK(fmt, ##__VA_ARGS__), ""); 
        boost::format f(fmt); 
        add(f, ##__VA_ARGS__); 
        std::cout << f.str() << std::endl; 
    }

int main()
{
    // nothing
    LOG("hello world");

    // char
    LOG("%c", 'x');

    // integral
    LOG("%d", -123);
    LOG("%ld", -123);
    LOG("%u", 123u);
    LOG("%lu", 123u);

    // strings
    LOG("%s", "hello world");
    LOG("%-s", "hello world");
    LOG("%s", std::string("hello world"));
    { const char* s = "hello world"; LOG("%s", s); }
    { std::string s = "hello world"; LOG("%s", s); }
    { std::string s = "hello world"; boost::string_ref r(s); LOG("%s", r); }

    // floating point
    LOG("%f", 1.23);
    LOG("%f", 1.23f);

    // width & precision
    LOG("%02d", 1);
    LOG("% 3s", "hello");
    LOG("% 3s", "yo");
    LOG("%.2d", 123);
    LOG("%.2f", 1.2345);
    LOG("%2f", 1.23456789);
    LOG("%02f", 0.1);
    LOG("%02.2f", 0.1);

    // width & precision as arguments
    // not supported by boost::format
//    LOG("%*d", 3, 12);
//    LOG("%.*s", 3, "hello");
//    LOG("%.*d", 3, 12345);
//    LOG("%*.*s", 3, 3, "hello");
//    LOG("%*.*d", 3, 3, 12345);

    // mix of multiple different arguments
    LOG("%s", "hi");
    LOG("%s %d", "hi", 1);
    LOG("%s %d %u %lf %f %c", "hi", -1, 12u, 1.23, 1.33, 'c');

    // too few arguments
//    LOG("%s %d %u %lf %f %c", "hi", -1, 12u, 1.23, 1.33);

    // too many arguments
//    LOG("%s %d %u %lf %f %c", "hi", -1, 12u, 1.23, 1.33, 'c', 1);

    // incorrect argument for format string
//    LOG("%s %d %u %lf %f %c", "hi", -1, 12u, 1, 1.33, 'c');
}

I can probably improve the %ll length specifier check as this is currently implemented as a backwards search into the format string for 64-bit integral types. I also haven’t done checking for %hh length specifier.

Error cases:

Too few arguments:

main.cpp:285:84: error: expression ‘<throw-expression>’ is not a constant-expression
             : throw std::logic_error("too few arguments for provided format string");

Too many arguments:

main.cpp:257:87: error: expression ‘<throw-expression>’ is not a constant-expression
                 throw std::logic_error("too many arguments for provided format string")

Mismatch between argument type and format:

main.cpp:29:68: error: expression ‘<throw-expression>’ is not a constant-expression
     { return C != c ? throw std::logic_error("invalid fmt for type") : true; } 
                                                                    ^
main.cpp:33:1: note: in expansion of macro ‘SUPPORTED_TYPE’
 SUPPORTED_TYPE(int,               'd');

The error TypeError: not enough arguments for format string occurs if the number of arguments you specify during string formatting is not equal to the number of values you want to add to the string. The error can also occur if you forget to enclose the values for string formatting in parentheses.

This tutorial will go through how to solve this error with code examples.


Table of contents

  • TypeError: not enough arguments for format string
    • What is a TypeError?
    • What is String Formatting in Python?
  • Example #1: Incorrect String Formatting Syntax
    • Solution #1: Use Parentheses
    • Solution #2: Use format()
    • Solution #3: Use f-string
  • Example #2: Not Enough Arguments
    • Solution: Use Correct Number of Arguments
  • Summary

TypeError: not enough arguments for format string

What is a TypeError?

TypeError tells us that we are trying to perform an illegal operation for a specific Python data type.

What is String Formatting in Python?

String formatting is the process of dynamically implanting values in a string and presenting a new string. There are four ways to perform string formatting in Python:

  • Formatting with % operator
  • Formatting with the built-in format() string method
  • Formatting with string literals, called f-strings
  • Formatting using the template class from the string module

We can use the % operator to infuse a set of variables enclosed in a tuple into a format string. The format string contains text with argument specifiers. For example, %s specifies a string argument and %d specifies an integer argument. Let’s look at an example of string formatting with the % operator.

name = "Paul"

age = 40

print("%s is %d years old." %(name, age))
Paul is 40 years old.

If you do not use parentheses to enclose the variables, you will raise the error: TypeError: not enough arguments for format string. Let’s look at examples of the error.

Example #1: Incorrect String Formatting Syntax

In the following example, we have a list of ice cream flavors. We want to format a string called popular_flavors to include the four flavors and print the resultant string to the console.

ice_cream_flavors = ["Vanilla", "Strawberry", "Chocolate", "Pistachio"]

popular_flavors = "%s, %s, %s, and %s are popular flavors of ice cream." % ice_cream_flavors[0], ice_cream_flavors[1], ice_cream_flavors[2], ice_cream_flavors[3]

print(popular_flavors)

Let’s run the code to get the result.

---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
1 popular_flavors = "%s, %s, %s, and %s are popular flavors of ice cream." % ice_cream_flavors[0], ice_cream_flavors[1], ice_cream_flavors[2], ice_cream_flavors[3]

TypeError: not enough arguments for format string

The program throws the error because we did not enclose the arguments in parentheses.

Solution #1: Use Parentheses

To solve the problem, we need to wrap the arguments in parentheses (), as shown below:

popular_flavors = "%s, %s, %s, and %s are popular flavors of ice cream." % (ice_cream_flavors[0], ice_cream_flavors[1], ice_cream_flavors[2], ice_cream_flavors[3])

print(popular_flavors)

Let’s run the code to get the result:

Vanilla, Strawberry, Chocolate, and Pistachio are popular flavors of ice cream.

Solution #2: Use format()

Alternatively, we can use the format() method. The .format() syntax differs from the % string formatting syntax. We need to use curly brackets {} as placeholders for our arguments in the format string and then call the format() method on that string with the required arguments. Let’s look at the revised code:

popular_flavors = "{}, {}, {}, and {} are popular flavors of ice cream.".format(ice_cream_flavors[0], ice_cream_flavors[1], ice_cream_flavors[2], ice_cream_flavors[3])

print(popular_flavors)

Let’s run the code to get the result:

Vanilla, Strawberry, Chocolate, and Pistachio are popular flavors of ice cream.

Solution #3: Use f-string

As of Python 3.6, you can use the string formatting method called literal string interpolation or f-strings. The method is a more straightforward approach to string formatting. To create an f-string, you need to prefix the string with the letter f. The syntax still requires curly brackets, but you place the variables inside the curly brackets. Let’s look at the revised code:

print(f"{ice_cream_flavors[0]}, {ice_cream_flavors[1]}, {ice_cream_flavors[2]}, and {ice_cream_flavors[3]} are popular flavors of ice cream.")
Vanilla, Strawberry, Chocolate, and Pistachio are popular flavors of ice cream.

The f-string provides a concise and convenient way to embed python expressions inside a string literal for formatting.

Example #2: Not Enough Arguments

Another common source of the error is not having the correct number of arguments to format the string. Let’s look at our ice cream flavors example:

ice_cream_flavors = ["Vanilla", "Strawberry", "Chocolate", "Pistachio"]

popular_flavors = "%s, %s, %s, and %s are popular flavors of ice cream." % (ice_cream_flavors[0], ice_cream_flavors[1], ice_cream_flavors[2])

print(popular_flavors)
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
1 popular_flavors = "%s, %s, %s, and %s are popular flavors of ice cream." % (ice_cream_flavors[0], ice_cream_flavors[1], ice_cream_flavors[2])

TypeError: not enough arguments for format string

The program throws the error because the format string has four argument specifiers, but we only pass three variables.

Solution: Use Correct Number of Arguments

We can solve this error by ensuring all variables present to format the string. Let’s look at the revised code:

popular_flavors = "%s, %s, %s, and %s are popular flavors of ice cream." % (ice_cream_flavors[0], ice_cream_flavors[1], ice_cream_flavors[2], ice_cream_flavors[3])

print(popular_flavors)

All four variables are present. Let’s run the code to get the result:

Vanilla, Strawberry, Chocolate, and Pistachio are popular flavors of ice cream.

This error can also happen if we have more variables than argument specifiers in our format string.

Summary

Congratulations on reading to the end of this tutorial! The error “TypeError: not enough arguments for format string” occurs when the number of arguments specified in the string formatting operation is not equal to the number of variables you want to add into the string.

First, ensure the number of variables equals the number of argument specifiers to solve this error. Then ensure that all variables are in tuple format with parenthesis and comma-separated if you use the % operator. You can use the format() method instead of the % operator. If you are using Python 3.6+, you can use the f-String approach, which has the simplest syntax and is the fastest type of string formatting.

For further reading on string manipulation, go to the article: How to Convert a String to an Int in Python.

For further reading on TypeErrors involving string formatting, go to the article: How to Solve Python TypeError: not all arguments converted during string formatting.

Go to the online courses page on Python to learn more about coding in Python for data science and machine learning.

Have fun and happy researching!

Понравилась статья? Поделить с друзьями:
  • Error tokenizing data c error expected 10 fields in line 6044 saw 11
  • Error tokenizing data c error expected 1 fields in line 28 saw 367
  • Error tokenizing data c error eof inside string starting at row
  • Error tokenizing data c error calling read nbytes on source failed try engine python
  • Error tofixed is not a function