Here is my attempt:

    def remove_too_long_reads(bam):
    
        for read in bam:
            if read.end - read.start < 60:
                yield read

    bam = BedTool(input.bam)
    bam = BedTool(remove_too_long_reads(bam))

But when I try to use the bam file afterwards like so:

    bam.intersect(...

I get an error:

> <class 'BrokenPipeError'>: Broken pipe The command was:
> 
>         bedtools intersect -b data/gencode_annotation/tss.bed -a stdin
> 
> Things to check: Error in job intersect_data_tss while creating output
> file data/tss/bam/Exp2_9h_PolII.bam. RuleException: KeyError in line
> 31 of
> /local/home/endrebak/code/programmable_epigenetics/rules/tss/intersect_bam_gencode.rules:
> 32   File
> "/local/home/endrebak/code/programmable_epigenetics/rules/tss/intersect_bam_gencode.rules",
> line 31, in __rule_intersect_data_tss   File
> "/local/home/endrebak/anaconda3/lib/python3.5/site-packages/pybedtools/bedtool.py",
> line 773, in decorated   File
> "/local/home/endrebak/anaconda3/lib/python3.5/site-packages/pybedtools/bedtool.py",
> line 336, in wrapped   File
> "/local/home/endrebak/anaconda3/lib/python3.5/site-packages/pybedtools/helpers.py",
> line 373, in call_bedtools
In order to maintain compatibility with VCF/BED/GFF/GTF functionality, pybedtools converts BAM/SAM reads into `pybedtools.Interval` objects. When just filtering on length as you're doing here, that's unnecessary overhead. Here's a more efficient way to do it with pysam, which also has the benefit of providing access to all the read details if you need to do more sophisticated filtering.  You can then use the filtered bam for downstream operations (e.g., histograms of read counts across intervals):

https://gist.github.com/daler/f44c19510860aeb29e8f75432eec8883