开发者

Execute python code without invoking import statement each time

Here is a sample python script. How do I run this script multiple times from command line so that the import line is not called every time? The import statement takes too long to load.

import arcpy
val = arcpy.GetCellValue_management("D:\dem-m开发者_Python百科erged\lidar_wsg84", "-95.090174910630012 29.973962146120652", "")
print str(val)


This problem has no solution if you strictly want this script "to be called from another program. by issuing 'python script.py' on command line". If you want to do the "heavy import" only once, you have to start python script only once. Think about starting a daemon, which will start once and then process calls from other program. This way all initialization has to be done only one time and next calls will be fast. And if you split your python code into two parts (first part for daemon, second for daemon client), you'll be able to call 'python client.py' from another program, but actual computation will be performed by daemon, which is started just one time.

As example:

daemon.py

import socket
#import arcpy

def actual_work():
    #val = arcpy.GetCellValue_management("D:\dem-merged\lidar_wsg84", "-95.090174910630012 29.973962146120652", "")
    #return str(val)
    return 'dummy_reply'


def main():
    sock = socket.socket( socket.AF_INET, socket.SOCK_DGRAM )
    try:
        sock.bind( ('127.0.0.1', 6666) )

        while True:
            data, addr = sock.recvfrom( 4096 )
            reply = actual_work()
            sock.sendto(reply, addr)
    except KeyboardInterrupt:
        pass
    finally:
        sock.close()


if __name__ == '__main__':
    main()

client.py

import socket
import sys


def main():
    sock = socket.socket( socket.AF_INET, socket.SOCK_DGRAM )
    sock.settimeout(1)
    try:
        sock.sendto('', ('127.0.0.1', 6666))
        reply, _ = sock.recvfrom(4096)
        print reply
    except socket.timeout:
        sys.exit(1)
    finally:
        sock.close()


if __name__ == '__main__':
    main()


It's virtually impossible. Once you leave the interpreter, the modules that were imported are no longer in the memory. It's similar to asking Firefox to save large webpages in memory because the read rate to the cache takes too long. Once Firefox (or Python) is shut off, it's pretty much bye-bye anything in the RAM.

You can make the load time faster, but at your own risk. By running

python -O 

you can make it go a bit faster. You can also add another 'O' to make it go just a bit faster. However, this can make some programs buggy and doesn't always work.

You could copy the functions you need into your program by doing

from arcpy import <what you need>

and that might make things go slightly faster.


As far as I know the module gets imported once. So if you do:

import a
import a

it only gets imported once. So instead of running the script many times, maybe you can change it to make all the copies in one go.

If you have to run this specific script many times, I think you can't avoid the import and you'll have to import it every time.


One solution I can think of is to have a server process that runs persistently that does the actual work, while the script that's actually invoked from the command line merely issues requests to that script. This is a fair bit of work, but it may be worth it.


The only solution I can think of is to copy the individual function(s) you need into your code manually, if what you need to execute is small enough.

If you need help on how to do this, just ask in the comments.


Looking at your use case (calling it from a Ruby on Rails webservice), one of the easiest ways would be to use XML-RPC. Use the SimpleXMLRPCServer from the python standard lib, and then use a ruby client (ruby seems to have xmlrpc in the standard lib)?


Easy.

Write your own simple shell using the cmd module and use the runpy module to run your scripts. Import you big module in the shell program and pass it to the programs using init_globals

Look through the docs for http://pypi.python.org/pypi/cmd2/ and it should be fairly clear how you can write your own simple shell, even if it just has two commands, one to edit a file and one to run it.

runpy is part of the Python standard library http://docs.python.org/library/runpy.html and you may not need it, but it is useful to know that the import and module loading mechanism can be controlled and even modified by your command shell.

Have you ever wondered where the name "var1" goes when you execute something like var1 = 25? How does Python find what var1 refers to when you later execute print var1? The answer is that these names are in a dictionary and if you understand what Python dictionaries are and what they can do, it seems like an obvious solution to the problem of connecting names with values. But there's more. Python can have lots of namespaces and you can manipulate those namespaces the same way you manipulate dictionaries. Read this http://www.diveintopython.net/html_processing/locals_and_globals.html to understand the locals and globals namespace. Here is another discussion that will help http://lucumr.pocoo.org/2011/2/1/exec-in-python/

Play around with exec like in this question globals and locals in python exec() until you understand how it works. Then build your command shell to import the module one time at the beginning, and write your scripts to only import the module if it is not already available. When the script is run from inside your shell, the module will already be there.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜