Asked  7 Months ago    Answers:  5   Viewed   40 times

I need to iterate through all .asm files inside a given directory and do some actions on them.

How can this be done in a efficient way?

 Answers

73

Original answer:

import os

for filename in os.listdir(directory):
    if filename.endswith(".asm") or filename.endswith(".py"): 
         # print(os.path.join(directory, filename))
        continue
    else:
        continue

Python 3.6 version of the above answer, using os - assuming that you have the directory path as a str object in a variable called directory_in_str:

import os

directory = os.fsencode(directory_in_str)
    
for file in os.listdir(directory):
     filename = os.fsdecode(file)
     if filename.endswith(".asm") or filename.endswith(".py"): 
         # print(os.path.join(directory, filename))
         continue
     else:
         continue

Or recursively, using pathlib:

from pathlib import Path

pathlist = Path(directory_in_str).glob('**/*.asm')
for path in pathlist:
     # because path is object not string
     path_in_str = str(path)
     # print(path_in_str)
  • Use rglob to replace glob('**/*.asm') with rglob('*.asm')
    • This is like calling Path.glob() with '**/' added in front of the given relative pattern:
from pathlib import Path

pathlist = Path(directory_in_str).rglob('*.asm')
for path in pathlist:
     # because path is object not string
     path_in_str = str(path)
     # print(path_in_str)
Tuesday, June 1, 2021
 
Eugenie
answered 7 Months ago
60

Seeing as you're already using antcontrib for, how about making use of the propertyselector task:

<property file="properties.txt" prefix="projects."/>
<propertyselector property="projects" match="projects.(.*)" select="1"/>

<property file="properties.txt" />
<for list="${projects}" param="project">
    ...
</for>

The idea here is to read the properties once with the projects prefix, and use the resulting set of properties to build a comma-separated list of projects with the propertyselector task. Then the properties are re-read without the prefix, so that your for loop can proceed as before.

Tuesday, August 10, 2021
 
rvictordelta
answered 4 Months ago
92

An iterator is an iterable, but an iterable is not necessarily an iterator.

An iterable is anything that has an __iter__ method defined - e.g. lists and tuples, as well as iterators.

Iterators are a subset of iterables whose values cannot all be accessed at the same time, as they are not all stored in memory at once. These can be generated using functions like map, filter and iter, as well as functions using yield.

In your example, map returns an iterator, which is also an iterable, which is why both functions work with it. However, if we take a list for instance:

>>> lst = [1, 2, 3]
>>> list(lst)
[1, 2, 3]
>>> next(lst)
Traceback (most recent call last):
  File "<pyshell#3>", line 1, in <module>
    next(lst)
TypeError: 'list' object is not an iterator

we can see that next complains, because the list, an iterable, is not an iterator.

Tuesday, August 17, 2021
 
Jeff Sherlock
answered 4 Months ago
42

What you're trying to do makes sense, but there's something evil going on inside Python here.

class foo(object):
    c = 0
    def __init__(self):
        self.next = self.next2

    def __iter__(self):
        return self

    def next(self):
        if self.c == 5: raise StopIteration
        self.c += 1
        return 1

    def next2(self):
        if self.c == 5: raise StopIteration
        self.c += 1
        return 2

it = iter(foo())
# Outputs: <bound method foo.next2 of <__main__.foo object at 0xb7d5030c>>
print it.next
# 2
print it.next()
# 1?!
for x in it:
    print x

foo() is an iterator which modifies its next method on the fly--perfectly legal anywhere else in Python. The iterator we create, it, has the method we expect: it.next is next2. When we use the iterator directly, by calling next(), we get 2. Yet, when we use it in a for loop, we get the original next, which we've clearly overwritten.

I'm not familiar with Python internals, but it seems like an object's "next" method is being cached in tp_iternext (http://docs.python.org/c-api/typeobj.html#tp_iternext), and then it's not updated when the class is changed.

This is definitely a Python bug. Maybe this is described in the generator PEPs, but it's not in the core Python documentation, and it's completely inconsistent with normal Python behavior.

You could work around this by keeping the original next function, and wrapping it explicitly:

class IteratorWrapper2(object):
    def __init__(self, otheriter):
        self.wrapped_iter_next = otheriter.next
    def __iter__(self):
        return self
    def next(self):
        return self.wrapped_iter_next()

for j in IteratorWrapper2(iter([1, 2, 3])):
    print j

... but that's obviously less efficient, and you should not have to do that.

Wednesday, September 15, 2021
 
kmunky
answered 3 Months ago
88

I seem to recall being able to call make recursively, something along the lines of:

all:
    -mkdir $(TEMPDIR)
    $(MAKE) $(MLAGS) old_all
    -rm -rf $(TEMPDIR)

old_all: ... rest of stuff.

I've done similar tricks for making in subdirectories:

all:
    @for i in $(SUBDIRS); do 
        echo "make all in $$i..."; 
        (cd $$i; $(MAKE) $(MLAGS) all); 
    done

Just checked it and this works fine:

$ cat Makefile
all:
    -mkdir tempdir
    -echo hello >tempdir/hello
    -echo goodbye >tempdir/goodbye
    $(MAKE) $(MFLAGS) old_all
    -rm -rf tempdir

old_all:
    ls -al tempdir

$ make all
mkdir tempdir
echo hello >tempdir/hello
echo goodbye >tempdir/goodbye
make  old_all
make[1]: Entering directory '/home/pax'
ls -al tempdir
total 2
drwxr-xr-x+ 2 allachan None 0 Feb 26 15:00 .
drwxrwxrwx+ 4 allachan None 0 Feb 26 15:00 ..
-rw-r--r--  1 allachan None 8 Feb 26 15:00 goodbye
-rw-r--r--  1 allachan None 6 Feb 26 15:00 hello
make[1]: Leaving directory '/home/pax'
rm -rf tempdir

$ ls -al tempdir
ls: cannot access tempdir: No such file or directory
Thursday, October 7, 2021
 
madphp
answered 2 Months ago
Only authorized users can answer the question. Please sign in first, or register a free account.
Not the answer you're looking for? Browse other questions tagged :  
Share