Filter out unwanted substrings while generating all possible relevant substrings
Use a generative approach

Iterating over all possible permutations and filtering out the invalid ones results in lots of wasted work.  Move the filtering operation earlier so many invalid permutations are not generated in the first place. 

For example, permute() contains for i in range(1, slen + 1), but we know that an octet can only be up to 3 digits long.  Change the loop to for i in range(1, min(4, len(s)+1)). Also, if first is not a valid octet skip the recursive call (none will result in a valid address).

Something like this:

def period_partition(s, k):

    def is_valid_octet(s):
        # section ranges 0 - 255 and `00` or `000`, `01` are not valid but 0 is
        return s == '0' or not s.startswith('0') and 0 &lt; int(s) &lt; 256

    if s and k:
        for i in range(1, min(4, len(s)+1)):
            first, rest = s[:i], s[i:]
            if is_valid_octet(first):
                yield from (f"{first}.{p}" for p in period_partition(rest, k-1))

    elif s and is_valid_octet(s):
        yield s


testcases = [
    ("", 1),
    ("1234", 2),
    ("19216811", 3),
    ("192168111234", 3),
    ("192168111234", 4),
    ("19216811123444", 4),
    ("192168111234444", 4),
]

for s, k in testcases:
    print(f"\nperiod_partition({s!r}, {k})")

    for partition in period_partition(s, k):
        print(f"  {partition}")


Note: I modified period_partition() to be a generator yields all valid partitions.  Use list() if you need an actual list.