# Printf with variable format string

**URL:** <https://discourse.julialang.org/t/printf-with-variable-format-string/3805>\
**Category:** General Usage\
**Tags:** strings, formatting, printf\
**Created:** [May 19, 2017, 10:53am UTC](https://discourse.julialang.org/t/printf-with-variable-format-string/3805 "2017-05-19T10:53:39Z")\
**Posts on this page:** 15\
**Page:** 1

<div class="post-metadata">

**Author:** ![baggepinnen](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/baggepinnen/32/693_2.png) [@baggepinnen](https://discourse.julialang.org/u/baggepinnen)\
**Post date:** [May 19, 2017, 10:53am UTC](https://discourse.julialang.org/t/printf-with-variable-format-string/3805/1 "2017-05-19T10:53:39Z")

</div>

Due to `@printf` being a macro, it does not accept a format string that has been passed as a variable.

```julia
myvec = randn(4)
n = length(myvec)
outstring = "Beginning of string with some numbers: "
for i = 1:n
   outstring = outstring*"%-12.3g"
end
outstring = outstring*"\n"
@printf(outstring, myvec...)

```

Is there currently a way to print using format strings without using a macro, or maybe a much smarter way I have failed to understand? The solution provided in

> [@Formatted printing of arrays](https://discourse.julialang.org/t/formatted-printing-of-arrays/3121):
>
> I want to print the elements of an array of floating point numbers in the same format. In Python/Numpy, I do: np.set\_printoptions(formatter={‘float’: ‘{: 10.6f}’.format, ‘complexfloat’: ‘{: 10.6f}’.format}) and the simple command “print someArray” will print the elements of an array in a uniform format. For example, I want arr = [1.0 2.583] to be printed as [1.000 2.583] rather than [1.0 2.583]. Is it possible to do this in Julia?

Changes the output for all `Float64` which is undesirable in my case.

Thanks in advance!

---

<div class="post-metadata">

**Author:** ![kristoffer.carlsson](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/kristoffer.carlsson/32/22_2.png) [@kristoffer.carlsson](https://discourse.julialang.org/u/kristoffer.carlsson)\
**Post date:** [May 19, 2017, 10:55am UTC](https://discourse.julialang.org/t/printf-with-variable-format-string/3805/2 "2017-05-19T10:55:41Z")

</div>

[https://github.com/JuliaIO/Formatting.jl](https://github.com/JuliaIO/Formatting.jl) perhaps. Seems that [https://github.com/JuliaIO/Formatting.jl/pull/30](https://github.com/JuliaIO/Formatting.jl/pull/30) is needed for 0.6 though.

---

<div class="post-metadata">

**Author:** ![baggepinnen](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/baggepinnen/32/693_2.png) [@baggepinnen](https://discourse.julialang.org/u/baggepinnen)\
**Post date:** [May 19, 2017, 11:01am UTC](https://discourse.julialang.org/t/printf-with-variable-format-string/3805/3 "2017-05-19T11:01:37Z")

</div>

That seems to solve the problem nicely, thank you 🙂

---

<div class="post-metadata">

**Author:** ![dpo](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dpo/32/3335_2.png) [@dpo](https://discourse.julialang.org/u/dpo)\
**Post date:** [May 19, 2017, 5:10pm UTC](https://discourse.julialang.org/t/printf-with-variable-format-string/3805/4 "2017-05-19T17:10:44Z")

</div>

It’s been a long-standing issue and I hope it is resolved one day. I’ve been calling libc’s `printf` directly sometimes. In other situations, the definition

```julia
print_formatted(fmt, args...) = @eval @printf($fmt, $(args...))

```

comes in handy but is very slow. You can get an idea of how performance is affected here: [https://gist.github.com/dpo/11000433](https://gist.github.com/dpo/11000433)

However, if you’re going to do lots of printing with one computed format string, `@eval` may be worthwhile. I use this approach when I know a format will be used many times, e.g., [https://github.com/JuliaSparse/HarwellRutherfordBoeing.jl/pull/6/files#diff-ebdd0a248bebc40afece10a0d03009daR20](https://github.com/JuliaSparse/HarwellRutherfordBoeing.jl/pull/6/files#diff-ebdd0a248bebc40afece10a0d03009daR20).

---

<div class="post-metadata">

**Author:** ![baggepinnen](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/baggepinnen/32/693_2.png) [@baggepinnen](https://discourse.julialang.org/u/baggepinnen)\
**Post date:** [May 21, 2017, 9:10am UTC](https://discourse.julialang.org/t/printf-with-variable-format-string/3805/5 "2017-05-21T09:10:27Z")

</div>

Thanks, in my intended application I will happily pay the performance penalty as long as it’s less than about 0.1s. Your solution seems to solve the problem just fine without the need for an additional package, thanks!

---

<div class="post-metadata">

**Author:** ![RaulDurand](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/rauldurand/32/2044_2.png) [@RaulDurand](https://discourse.julialang.org/u/RaulDurand)\
**Post date:** [November 9, 2018, 4:04am UTC](https://discourse.julialang.org/t/printf-with-variable-format-string/3805/6 "2018-11-09T04:04:55Z")

</div>

I think that a native function would be preferable instead of a package or the @eval solution.

---

<div class="post-metadata">

**Author:** ![o314](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/o314/32/252_2.png) [@o314](https://discourse.julialang.org/u/o314)\
**Post date:** [July 14, 2020, 3:31am UTC](https://discourse.julialang.org/t/printf-with-variable-format-string/3805/7 "2020-07-14T03:31:55Z")

</div>

I am personally not very fond of Formatting.jl - not enough lean

A short (and clean i hope) solution can be to gen closure with a macro according to the classical show signature

```nohighlight
import Printf

macro gprintf(fmt::String)
    :((io::IO, arg) -> Printf.@printf(io, $fmt, arg))
end

# can be used like this
const fi = @gprintf "%d"
const f3p = @gprintf "%.3f"
const f6p = @gprintf "%.6f"
jit_printf(fmt) = @eval @gprintf($fmt)

using Test
@testset "printf_functionalization" begin
    @test sprint(f3p, 3.14) == "3.140"
    @test sprint(f6p, 3.14) == "3.140000"
    @testset for i in 3:8
        fmt = string("%.", i, "f")
        fjp = @eval @gprintf($fmt) # <=> fjp = jit_printf(fmt)
        @test sprint(fjp, 3.14) == "3.14" * repeat('0', i-2)
    end
end

```

PS: BTW @RaulDurand that fix your point, no external package, no eval

---

<div class="post-metadata">

**Author:** ![bjarthur](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/bjarthur/32/9638_2.png) [@bjarthur](https://discourse.julialang.org/u/bjarthur)\
**Post date:** [May 22, 2023, 1:00pm UTC](https://discourse.julialang.org/t/printf-with-variable-format-string/3805/8 "2023-05-22T13:00:54Z")

</div>

still can’t use variable format strings with `@printf` in julia 1.9 ☹

```julia
julia> using Printf

julia> fmt = "%d"
"%d"

julia> @printf fmt 16
ERROR: LoadError: ArgumentError: First argument to `@printf` after `io` must be a format string
Stacktrace:
 [1] var"@printf"( __source__ ::LineNumberNode, __module__ ::Module, io_or_fmt::Any, args::Vararg{Any})
   @ Printf ~/.julia/juliaup/julia-1.9.0+0.aarch64.apple.darwin14/share/julia/stdlib/v1.9/Printf/src/Printf.jl:943
in expression starting at REPL[3]:1

```

---

<div class="post-metadata">

**Author:** ![Paul\_Soderlind](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/paul_soderlind/32/1753_2.png) [@Paul\_Soderlind](https://discourse.julialang.org/u/Paul_Soderlind)\
**Post date:** [May 22, 2023, 1:37pm UTC](https://discourse.julialang.org/t/printf-with-variable-format-string/3805/9 "2023-05-22T13:37:55Z")

</div>

try `Printf.format()`

---

<div class="post-metadata">

**Author:** ![bjarthur](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/bjarthur/32/9638_2.png) [@bjarthur](https://discourse.julialang.org/u/bjarthur)\
**Post date:** [May 22, 2023, 5:14pm UTC](https://discourse.julialang.org/t/printf-with-variable-format-string/3805/10 "2023-05-22T17:14:08Z")

</div>

thanks so much @Paul_Soderlind !

since `format` is not exported, and so isn’t [documented](https://docs.julialang.org/en/v1/stdlib/Printf/), here’s specifically what i got to work:

```julia
julia> using Printf

julia> w=9
9

julia> fmt = Printf.Format("%$(w)d")
Printf.Format{Base.CodeUnits{UInt8, String}, Tuple{Printf.Spec{Val{'d'}}}}(UInt8[0x25, 0x39, 0x64], UnitRange{Int64}[1:0, 4:3], (%9.0d,))

julia> Printf.format(stdout, fmt,16)
       16

```

---

<div class="post-metadata">

**Author:** ![Henrique\_Becker](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/henrique_becker/32/15443_2.png) [@Henrique\_Becker](https://discourse.julialang.org/u/Henrique_Becker)\
**Post date:** [May 22, 2023, 5:41pm UTC](https://discourse.julialang.org/t/printf-with-variable-format-string/3805/11 "2023-05-22T17:41:35Z")

</div>

What do you mean by “isn’t documented”? It is, in fact, documented. You have a link to its documentation in your post.

---

<div class="post-metadata">

**Author:** ![fatteneder](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/fatteneder/32/33991_2.png) [@fatteneder](https://discourse.julialang.org/u/fatteneder)\
**Post date:** [May 22, 2023, 5:54pm UTC](https://discourse.julialang.org/t/printf-with-variable-format-string/3805/12 "2023-05-22T17:54:24Z")

</div>

> [@Using a variable to format printf not allowed?](https://discourse.julialang.org/t/using-a-variable-to-format-printf-not-allowed/99200/7):
>
> Like @Barget said, try the ? operator: help?\> Printf.Format Printf.Format(format\_str) Create a C printf-compatible format object that can be used for formatting values. The input format\_str can include any valid format specifier character and modifiers. A Format object can be passed to Printf.format(f::Format, args...) to produce a formatted string, or Printf.format(io::IO, f::Format, args...) to print the formatted string directly to io. For convenience, the Printf.format"..…

---

<div class="post-metadata">

**Author:** ![PeterSimon](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/petersimon/32/25193_2.png) [@PeterSimon](https://discourse.julialang.org/u/PeterSimon)\
**Post date:** [May 22, 2023, 6:01pm UTC](https://discourse.julialang.org/t/printf-with-variable-format-string/3805/13 "2023-05-22T18:01:03Z")

</div>

There is a docstring for `Printf.Format`:

```julia
julia> using Printf

help?> Printf.Format
  Printf.Format(format_str)

  Create a C printf-compatible format object that can be used
  for formatting values.

  The input format_str can include any valid format specifier
  character and modifiers.

  A Format object can be passed to Printf.format(f::Format,
  args...) to produce a formatted string, or
  Printf.format(io::IO, f::Format, args...) to print the
  formatted string directly to io.

  For convenience, the Printf.format"..." string macro form
  can be used for building a Printf.Format object at
  macro-expansion-time.

  │ Julia 1.6
  │
  │ Printf.Format requires Julia 1.6 or later.

```

Edit: Sorry, I didn’t initially see that this response is identical to that of @fatteneder.

---

<div class="post-metadata">

**Author:** ![bjarthur](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/bjarthur/32/9638_2.png) [@bjarthur](https://discourse.julialang.org/u/bjarthur)\
**Post date:** [May 22, 2023, 8:28pm UTC](https://discourse.julialang.org/t/printf-with-variable-format-string/3805/14 "2023-05-22T20:28:33Z")

</div>

there is a docstring, yes, but what i was pointing out is that neither `Printf.format` nor `Printf.Format` are mentioned in the user manual. just trying to make it easier for folks until they are.

---

<div class="post-metadata">

**Author:** ![bertschi](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/bertschi/32/33462_2.png) [@bertschi](https://discourse.julialang.org/u/bertschi)\
**Post date:** [May 22, 2023, 9:04pm UTC](https://discourse.julialang.org/t/printf-with-variable-format-string/3805/15 "2023-05-22T21:04:55Z")

</div>

Imho, `printf` should not be a macro in the first place. In the end, its just a small performance optimization precompiling the format string, i.e., it doesn’t buy much as compared to its underlying functions:

```julia
julia> @macroexpand @printf "%d" 123
:((Printf).format(stdout, Printf.Format{Base.CodeUnits{UInt8, String}, Tuple{Printf.Spec{Val{'d'}}}}(UInt8[0x25, 0x64], UnitRange{Int64}[1:0, 3:2], (%.0d,)), 123))

# So basically the same as
julia> Printf.format(stdout, Printf.format"%d", 123)
123
# i.e. with the format_str macro precompiling the Format
 
# Why not just define ...
julia> printf(fmt::Printf.Format, args...) = Printf.format(stdout, fmt, args...)

julia> printf(io::IO, fmt::Printf.Format, args...) = Printf.format(io, fmt, args...)

julia> macro fmt_str(s) Printf.Format(s) end

# and be happy
julia> printf(fmt"%d", 123)
123

```

Am I missing something here, i.e., also Rust decided on format being a macro?
