# ANN: Exfiltrator

**URL:** <https://discourse.julialang.org/t/ann-exfiltrator/44455>\
**Category:** Community\
**Created:** [August 6, 2020, 8:48pm UTC](https://discourse.julialang.org/t/ann-exfiltrator/44455 "2020-08-06T20:48:31Z")\
**Posts on this page:** 17\
**Page:** 1

<div class="post-metadata">

**Author:** ![antoine-levitt](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/antoine-levitt/32/4008_2.png) [@antoine-levitt](https://discourse.julialang.org/u/antoine-levitt)\
**Post date:** [August 6, 2020, 8:48pm UTC](https://discourse.julialang.org/t/ann-exfiltrator/44455/1 "2020-08-06T20:48:31Z")

</div>

Exfiltrator ([https://github.com/antoine-levitt/Exfiltrator.jl](https://github.com/antoine-levitt/Exfiltrator.jl)) is Infiltrator’s younger sibling. It exfiltrates local variables to the global scope for easier exploration in the REPL. Example from the readme:

```julia
using Exfiltrator

julia> function f(x)
           @exfiltrate
       end
f (generic function with 1 method)

julia> f(2)

julia> x
2

```

There’s also a few variants eg to export variables from multiple calls. Exfiltrator is useful either to debug a program or to export results from deep call stacks (eg for plotting). Feedback welcome!

---

<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:** [August 6, 2020, 9:14pm UTC](https://discourse.julialang.org/t/ann-exfiltrator/44455/2 "2020-08-06T21:14:32Z")

</div>

Could

```julia
@testset "foo" begin
    @exfiltrate
    z = 3
end

```

be made to work?

---

<div class="post-metadata">

**Author:** ![antoine-levitt](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/antoine-levitt/32/4008_2.png) [@antoine-levitt](https://discourse.julialang.org/u/antoine-levitt)\
**Post date:** [August 7, 2020, 7:56am UTC](https://discourse.julialang.org/t/ann-exfiltrator/44455/3 "2020-08-07T07:56:43Z")

</div>

That one is pretty much impossible, because the declaration of z is after the exfiltrate call so it’s not defined at that point. I thought about supporting `@exfiltrate VAR function f()... ` and `@exfiltrate VAR begin... `which would exfiltrate all locals at the end of the call. That would take care of your case.

---

<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:** [August 7, 2020, 8:21am UTC](https://discourse.julialang.org/t/ann-exfiltrator/44455/4 "2020-08-07T08:21:05Z")

</div>

Oh, so I can just put it at the end? That works as well.

---

<div class="post-metadata">

**Author:** ![antoine-levitt](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/antoine-levitt/32/4008_2.png) [@antoine-levitt](https://discourse.julialang.org/u/antoine-levitt)\
**Post date:** [August 7, 2020, 9:01am UTC](https://discourse.julialang.org/t/ann-exfiltrator/44455/5 "2020-08-07T09:01:36Z")

</div>

Sure: it just takes its information from Base.@locals, which gives all the currently defined variables.

---

<div class="post-metadata">

**Author:** ![pdeffebach](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/pdeffebach/32/10320_2.png) [@pdeffebach](https://discourse.julialang.org/u/pdeffebach)\
**Post date:** [August 7, 2020, 1:30pm UTC](https://discourse.julialang.org/t/ann-exfiltrator/44455/6 "2020-08-07T13:30:06Z")

</div>

Thank you! I like R’s `browser()` and `@infiltrate` but sometimes feel constricted by the special REPL. I will definitely use this!

---

<div class="post-metadata">

**Author:** ![hendri54](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/hendri54/32/9621_2.png) [@hendri54](https://discourse.julialang.org/u/hendri54)\
**Post date:** [August 7, 2020, 7:17pm UTC](https://discourse.julialang.org/t/ann-exfiltrator/44455/7 "2020-08-07T19:17:34Z")

</div>

And, remarkably, it’s 37 lines of code.

---

<div class="post-metadata">

**Author:** ![antoine-levitt](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/antoine-levitt/32/4008_2.png) [@antoine-levitt](https://discourse.julialang.org/u/antoine-levitt)\
**Post date:** [August 7, 2020, 8:14pm UTC](https://discourse.julialang.org/t/ann-exfiltrator/44455/8 "2020-08-07T20:14:53Z")

</div>

Oh yeah, the thing is completely trivial thanks to the `Base.@locals` macro, I kind of feel bad for publishing such a stupid thing but it’s useful so… Maybe it could get merged in Infiltrator.jl because it’s similar in purpose, but the name would clash a bit.

Credits go to the people in the slack thread on debugging who said their debugging process is basically exporting variables to the global scope, and to @StefanKarpinski for the idea to just export the variables directly (my previous version exported named tuples only)

---

<div class="post-metadata">

**Author:** ![BioTurboNick](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/bioturbonick/32/6380_2.png) [@BioTurboNick](https://discourse.julialang.org/u/BioTurboNick)\
**Post date:** [August 12, 2020, 3:12pm UTC](https://discourse.julialang.org/t/ann-exfiltrator/44455/9 "2020-08-12T15:12:38Z")

</div>

This (and Infiltrator) both look pretty useful. Thanks!

---

<div class="post-metadata">

**Author:** ![pdeffebach](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/pdeffebach/32/10320_2.png) [@pdeffebach](https://discourse.julialang.org/u/pdeffebach)\
**Post date:** [August 12, 2020, 3:14pm UTC](https://discourse.julialang.org/t/ann-exfiltrator/44455/10 "2020-08-12T15:14:47Z")

</div>

I’ve been using it and it’s exactly what I needed. Much easier to write data-cleaning code in functions and know where things go wrong.

---

<div class="post-metadata">

**Author:** ![NightMachinary](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/nightmachinary/32/14196_2.png) [@NightMachinary](https://discourse.julialang.org/u/NightMachinary)\
**Post date:** [August 12, 2020, 4:10pm UTC](https://discourse.julialang.org/t/ann-exfiltrator/44455/11 "2020-08-12T16:10:58Z")

</div>

This is awesome! It might be only 37 lines of code, but a lot of UI design is trivial but hard to conceive. There is also a knowledge barrier, i.e., I do not know how to implement this macro (I did not know about `Base.@locals` either), so even though I might have thought of this, because I couldn’t know how much time learning to implement it would take me, I would dismiss the thought.

---

<div class="post-metadata">

**Author:** ![pdeffebach](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/pdeffebach/32/10320_2.png) [@pdeffebach](https://discourse.julialang.org/u/pdeffebach)\
**Post date:** [August 21, 2020, 3:43pm UTC](https://discourse.julialang.org/t/ann-exfiltrator/44455/12 "2020-08-21T15:43:54Z")

</div>

Is there some trick to using `@exfiltrate` in package development? I want to be able to put `@exfiltrate` inside a function in a package, but I don’t necessarily want to add `Exfiltrator` as a dependency

---

<div class="post-metadata">

**Author:** ![antoine-levitt](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/antoine-levitt/32/4008_2.png) [@antoine-levitt](https://discourse.julialang.org/u/antoine-levitt)\
**Post date:** [August 21, 2020, 4:55pm UTC](https://discourse.julialang.org/t/ann-exfiltrator/44455/13 "2020-08-21T16:55:58Z")

</div>

I usually just add `using Exfiltrator` at the beginning of a file and Revise takes care of it. It’d be great to get rid of the using but I don’t know how

---

<div class="post-metadata">

**Author:** ![oxinabox](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/oxinabox/32/206603_2.png) [@oxinabox](https://discourse.julialang.org/u/oxinabox)\
**Post date:** [August 21, 2020, 5:32pm UTC](https://discourse.julialang.org/t/ann-exfiltrator/44455/14 "2020-08-21T17:32:15Z")

</div>

add it to your global enviroment.  
then it doesn;t have to be in the project’s dependnecies

---

<div class="post-metadata">

**Author:** ![cstjean](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/cstjean/32/1444_2.png) [@cstjean](https://discourse.julialang.org/u/cstjean)\
**Post date:** [August 21, 2020, 6:01pm UTC](https://discourse.julialang.org/t/ann-exfiltrator/44455/15 "2020-08-21T18:01:29Z")

</div>

Wait, can packages access global dependencies? I thought they were only visible at the REPL.

> [@pdeffebach](#):
>
> Is there some trick to using `@exfiltrate` in package development? I want to be able to put `@exfiltrate` inside a function in a package, but I don’t necessarily want to add `Exfiltrator` as a dependency

I would try `using Exfiltrator` at the REPL, then in the package code use `Main.@exfiltrate`

---

<div class="post-metadata">

**Author:** ![antoine-levitt](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/antoine-levitt/32/4008_2.png) [@antoine-levitt](https://discourse.julialang.org/u/antoine-levitt)\
**Post date:** [August 21, 2020, 7:55pm UTC](https://discourse.julialang.org/t/ann-exfiltrator/44455/16 "2020-08-21T19:55:21Z")

</div>

> [@cstjean](#):
>
> I would try `using Exfiltrator` at the REPL, then in the package code use `Main.@exfiltrate`

Good trick, thanks!

---

<div class="post-metadata">

**Author:** ![heliosdrm](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/heliosdrm/32/3851_2.png) [@heliosdrm](https://discourse.julialang.org/u/heliosdrm)\
**Post date:** [August 21, 2020, 8:26pm UTC](https://discourse.julialang.org/t/ann-exfiltrator/44455/17 "2020-08-21T20:26:43Z")

</div>

> [@cstjean](#):
>
> I would try `using Exfiltrator` at the REPL, then in the package code use `Main.@exfiltrate`

Thanks! Actually I had the same question for Infiltrator.jl. This is a very smart trick.

However, the lines with `Main.@exfiltrate` will still throw an error if you forget to delete them after debugging. I have not yet tested it, but perhaps that could be avoided with:

```julia
isdefined(Main, :Exfiltrator) && Main.Exfiltrator.@exfiltrate

```

(Added `Main.Exfiltrator` in case the package it is “imported”, instead of “used”.)
